[Ynoi2018] 五彩斑斓的世界
由乃OI的卡常题......
CF896E Welcome home, Chtholly 传送门
以上两个传送门是CF上的,3000ms、512Mb。
这个 洛谷 P4117 [Ynoi2018]五彩斑斓的世界 是1000ms、128Mb(卡常+卡空间)。
这道题的修改操作很特殊,是对区间内某些拥有特殊性质的数进行操作。
各种数据结构无法满足这个要求,所以我们考虑分块。
把块内值相等的数用并查集连到一起,每个值记录一个head就行了。
但是如果块内全是大于x的数,我们需要对所有的head进行操作,复杂度太高了。
所以如果有一半以上都是大于x的,考虑将不大于x的都加上x,再打个标记让整个块减少x就行了。
其实时间空间也不是太卡,稍微搞一搞就能过了。
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 5 using std::max; 6 using std::min; 7 typedef unsigned int ui; 8 9 ui n,m,sz; 10 ui v[100001],hv[100001]; 11 ui f[100001],hd[225][100001]; 12 ui l[225],r[225],cnt[100001]; 13 ui bl[100001],mx[225],lz[225]; 14 15 ui read() 16 { 17 char c=getchar();ui ret=0u; 18 while(c<'0'||c>'9')c=getchar(); 19 while(c>='0'&&c<='9')ret=ret*10u+c-'0',c=getchar(); 20 return ret; 21 } 22 23 void getmx(ui id) 24 { 25 while(!hd[id][mx[id]])mx[id]--; 26 } 27 28 ui fin,bef; 29 30 ui fa(ui p) 31 { 32 fin=p; 33 while(fin^f[fin])fin=f[fin]; 34 while(f[p]^fin)bef=p,p=f[p],f[bef]=fin; 35 return fin; 36 } 37 38 void reset(ui id) 39 { 40 ui i; 41 for(i=l[id];i<=r[id];i++)v[i]=hv[fa(i)],hd[id][v[i]]=0u; 42 for(i=l[id];i<=r[id];i++)f[i]=i,cnt[i]=1u; 43 for(i=l[id];i<=r[id];i++) 44 { 45 if(hd[id][v[i]]) 46 f[i]=hd[id][v[i]],cnt[hd[id][v[i]]]+=cnt[i]; 47 else 48 hd[id][v[i]]=i,hv[i]=v[i]; 49 } 50 getmx(id); 51 } 52 53 void change(ui id,ui lb,ui rb,ui x) 54 { 55 ui i; 56 for(i=l[id];i<=r[id];i++)v[i]=hv[fa(i)]; 57 for(i=l[id];i<=r[id];i++)hd[id][v[i]]=0u; 58 for(i=lb;i<=rb;i++)if(v[i]-lz[id]>x)v[i]-=x; 59 for(i=l[id];i<=r[id];i++)f[i]=i,hv[i]=v[i]; 60 reset(id); 61 } 62 63 int main() 64 { 65 n=read(),m=read();sz=(ui)(sqrt(2*n)); 66 ui i,j;ui *fr,*to; 67 for(i=1u;i<=n;i++){bl[i]=(i-1u)/sz+1u;f[i]=i;} 68 for(i=1u;i<=bl[n];i++){l[i]=(i-1u)*sz+1u;r[i]=min(n,i*sz);} 69 for(i=1u;i<=n;i++) 70 {v[i]=hv[i]=read();mx[bl[i]]=max(mx[bl[i]],v[i]);} 71 for(i=1u;i<=bl[n];i++)reset(i); 72 ui op,lb,rb,x; 73 while(m--) 74 { 75 op=read(),lb=read(),rb=read(),x=read(); 76 if(op==1u) 77 { 78 if(bl[lb]==bl[rb]) 79 { 80 change(bl[lb],lb,rb,x); 81 continue; 82 } 83 change(bl[lb],lb,r[bl[lb]],x); 84 change(bl[rb],l[bl[rb]],rb,x); 85 for(i=bl[lb]+1u;i<bl[rb];i++) 86 { 87 if((x<<1)>mx[i]-lz[i]) 88 { 89 for(j=x+lz[i]+1u;j<=mx[i];j++) 90 { 91 fr=&hd[i][j],to=&hd[i][j-x]; 92 if(!(*fr))continue; 93 if(*to){cnt[*to]+=cnt[*fr];f[*fr]=*to;} 94 else{(*to)=(*fr);hv[*to]=j-x;} 95 *fr=0u; 96 } 97 getmx(i); 98 } 99 else 100 { 101 for(j=lz[i]+1u;j<=x+lz[i];j++) 102 { 103 fr=&hd[i][j],to=&hd[i][j+x]; 104 if(!(*fr))continue; 105 if(*to){cnt[*to]+=cnt[*fr];f[*fr]=*to;} 106 else{(*to)=(*fr);hv[*to]=j+x;} 107 *fr=0u; 108 } 109 lz[i]+=x; 110 } 111 } 112 } 113 if(op==2u) 114 { 115 ui ans=0u; 116 if(bl[lb]==bl[rb]) 117 { 118 for(i=lb;i<=rb;i++) 119 if(hv[fa(i)]==x+lz[bl[lb]])ans++; 120 printf("%u\n",ans); 121 continue; 122 } 123 for(i=lb;i<=r[bl[lb]];i++) 124 if(hv[fa(i)]==x+lz[bl[lb]])ans++; 125 for(i=l[bl[rb]];i<=rb;i++) 126 if(hv[fa(i)]==x+lz[bl[rb]])ans++; 127 for(i=bl[lb]+1u;i<bl[rb];i++) 128 if(x+lz[i]<=100000u)ans+=cnt[hd[i][x+lz[i]]]; 129 printf("%u\n",ans); 130 } 131 } 132 return 0; 133 }