csp-s模拟测试49(9.22)养花(分块/主席树)·折射(神仙DP)·画作
作者:互联网
最近有点头晕...........
T1 养花
考场我没想到正解,后来打的主席树,对于每个摸数查找1-(k-1),k-(2k-1)。。。的最大值,事实上还是很容易被卡的但是没有数据好像还比较友善,
对于求一段区间的最大值,因为建的是权值线段树,所以只需查找满足在查找的这段权值的区间内并且在L-R之内就好
在区间查询上稍改一下
正解分块咕了.....
***********************
查找mod某数的最大值,可以查1-(k-1)。。。拆开查询
1 #include<bits/stdc++.h> 2 #define MAXN 110000 3 using namespace std; 4 int tot=0;int a[MAXN],f[30][MAXN];int n,m; 5 int read(){ 6 int x=0;char c=getchar();int f=1; 7 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 8 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();} 9 return x; 10 } 11 struct node{int ls,rs,sum,me;}t[MAXN*100]; 12 void insert(int &now,int x,int L,int R){ 13 if(now==0)now=++tot; 14 int mid=(L+R)>>1; 15 if(L==R){t[now].sum++;t[now].me=x;return ;} 16 if(x<=mid)insert(t[now].ls,x,L,mid); 17 else insert(t[now].rs,x,mid+1,R); 18 t[now].sum=t[t[now].ls].sum+t[t[now].rs].sum; 19 } 20 int merge(int x,int y){ 21 if(!x||!y)return x+y; 22 t[x].ls=merge(t[x].ls,t[y].ls); 23 t[x].rs=merge(t[x].rs,t[y].rs); 24 t[x].sum+=t[y].sum; 25 return x; 26 } 27 int find(int now,int last){ 28 int nowls=t[now].ls;int nowrs=t[now].rs; 29 int lastls=t[last].ls;int lastrs=t[last].rs; 30 if(!nowls&&!nowrs){return t[now].me;} 31 if(t[nowrs].sum-t[lastrs].sum>0){return find(nowrs,lastrs);} 32 else if(t[nowls].sum-t[lastls].sum>0){return find(nowls,lastls);} 33 else return 0; 34 } 35 int maxn=0;int ok=0;int logg[MAXN]; 36 void ask(int now,int last,int l,int r,int L,int R,int k){ 37 if(ok==1)return ; 38 if(l<=L&&r>=R){ 39 if(t[now].sum>t[last].sum){maxn=max(maxn,find(now,last)%k);ok=1;} 40 return ; 41 } 42 int mid=(L+R)>>1; 43 if(r>mid) ask(t[now].rs,t[last].rs,l,r,mid+1,R,k); 44 if(l<=mid)ask(t[now].ls,t[last].ls,l,r,L,mid,k); 45 } 46 int RMB(int l,int r){ 47 int t=logg[r-l+1]/logg[2]; 48 return max(f[t][l],f[t][r-(1<<t)+1]); 49 } 50 void init(){ 51 for(int i=1;i<=n;++i)f[0][i]=a[i]; 52 for(int j=1;j<=29;++j){ 53 for(int i=1;i+(1<<j)-1<=n;++i){ 54 f[j][i]=max(f[j-1][i],f[j-1][i+(1<<(j-1))]); 55 } 56 } 57 } 58 int rt[MAXN];int mmm=0; 59 int voi(int l,int r,int k1,int k2,int k){ 60 int mt=0; 61 for(int i=l;i<=r;++i){ 62 if(a[i]>=k1&&a[i]<=k2){ 63 mt=max(mt,a[i]%k); 64 } 65 } 66 return mt; 67 } 68 signed main(){ 69 //freopen("t1.in","r",stdin); 70 //freopen("aa.out","w",stdout); 71 n=read();m=read(); 72 for(int i=1;i<=n;++i)logg[i]=log(i)/log(2); 73 for(int i=1;i<=n;++i){ 74 a[i]=read(); 75 mmm=max(a[i],mmm); 76 } 77 init(); 78 for(int i=1;i<=n;++i)insert(rt[i],a[i],0,mmm); 79 for(int i=1;i<=n;++i)rt[i]=merge(rt[i],rt[i-1]); 80 for(int i=1;i<=m;++i){ 81 maxn=0;int l=0,r=0,k=0;ok=0; 82 l=read();r=read();k=read(); 83 for(int pt=1;pt<=RMB(l,r)/k+1;++pt){ 84 ok=0; 85 ask(rt[r],rt[l-1],(pt-1)*k,pt*k-1,0,mmm,k); 86 } 87 printf("%d\n",maxn); 88 } 89 }View Code
T2 折射
考场大概只看出了n^3DP,用树状数组优化一下成了n^2log(n),事实上快结束时看出可以改成n^2前缀和即可
但是内存炸了,考场有没看清内存,不然卡一卡能拿80
然后正解思路清奇
我们按x排序,然后f[i][0]表示以i为顶点,向左连边,f[i][1]表示以i为顶点,向右连边
然后对于j而言,如果b[j]>b[i],则证明j才是折线的顶点,那么就是用i改j
如果b[i]>b[j]那么就是i为定点,用j改i
1 #include<bits/stdc++.h> 2 #define MAXN 6100 3 using namespace std; 4 const int mod=1e9+7; 5 int f[MAXN];struct node{int a,b;}e[MAXN]; 6 int n; 7 bool cmp(node aa,node bb){ 8 if(aa.b==bb.b)return aa.a>bb.a; 9 return aa.b>bb.b; 10 } 11 int c[MAXN][MAXN];int yuan[MAXN];int maxn=0; 12 int query(int x,int ad){ 13 return c[x][ad]%mod; 14 } 15 int ans=0; 16 signed main(){ 17 //freopen("t2.in","r",stdin); 18 //freopen("bb.out","w",stdout); 19 scanf("%d",&n); 20 for(int i=1;i<=n;++i){scanf("%d%d",&e[i].a,&e[i].b);yuan[++yuan[0]]=e[i].a;} 21 sort(yuan+1,yuan+yuan[0]+1); 22 int kx=unique(yuan+1,yuan+yuan[0]+1)-yuan-1; 23 for(int i=1;i<=n;++i){ 24 e[i].a=lower_bound(yuan+1,yuan+kx+1,e[i].a)-yuan; 25 maxn=max(maxn,e[i].a); 26 } 27 sort(e+1,e+n+1,cmp); 28 for(int i=2;i<=n;++i){ 29 memset(f,0,sizeof(f)); 30 for(int j=1;j<i;++j){ 31 if(e[j].b<=e[i].b)continue; 32 if(e[i].a==e[j].a)continue; 33 f[e[j].a]++; 34 if(e[i].a<e[j].a){ 35 f[e[j].a]=(f[e[j].a]+query(j,e[i].a-1))%mod; 36 } 37 else{ 38 f[e[j].a]=(f[e[j].a]+query(j,maxn)-query(j,e[i].a)+mod)%mod; 39 } 40 //printf("f[%d]=%d\n",e[j].a,f[e[j].a]); 41 } 42 for(int j=1;j<=maxn;++j){ 43 c[i][j]=(f[j]+c[i][j-1])%mod; 44 } 45 } 46 for(int i=1;i<=n;++i)ans=(ans+c[i][maxn])%mod; 47 printf("%d\n",(ans+n)%mod); 48 }暴力
1 #include<bits/stdc++.h> 2 #define MAXN 6100 3 using namespace std; 4 const int mod=1e9+7; 5 int f[MAXN][2]; 6 int n; 7 struct node{int a,b;}e[MAXN]; 8 bool cmp(node aa,node bb){ 9 return aa.a<bb.a; 10 } 11 long long ans=0; 12 signed main(){ 13 //freopen("t2.in","r",stdin); 14 //freopen("bb.out","w",stdout); 15 scanf("%d",&n); 16 for(int i=1;i<=n;++i){scanf("%d%d",&e[i].a,&e[i].b);} 17 sort(e+1,e+n+1,cmp); 18 for(int i=1;i<=n;++i){ 19 //printf("e[%d].a=%d e[%d].b=%d\n",i,e[i].a,i,e[i].b); 20 f[i][0]=1,f[i][1]=1; 21 if(e[i].a==e[i-1].a)continue; 22 for(int j=i-1;j>=1;--j){ 23 if(e[j].b<e[i].b){ 24 f[i][0]=(f[i][0]%mod+f[j][1]%mod)%mod; 25 } 26 else if(e[j].b>e[i].b){ 27 f[j][1]=(f[j][1]%mod+f[i][0]%mod)%mod; 28 } 29 } 30 } 31 for(int i=1;i<=n;++i){ 32 ans=(ans+f[i][0]%mod); 33 ans=(ans+f[i][1]-1+mod)%mod; 34 } 35 printf("%lld\n",ans%mod); 36 }View Code
***************************
1.注意内存。
2.结合图像思路转化
T3
还没改过来,做的有点慢了
标签:9.22,return,bb,49,int,MAXN,now,DP,mod 来源: https://www.cnblogs.com/Wwb123/p/11568849.html