算导:
核算法
给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量。
当实际代价小于摊还代价时,增加等于差额的信用;
当实际代价大于摊还代价时,减少等于差额的信用。
显然总摊还代价等于总实际代价+总信用变化量。
如果信用变化量始终>=0,那么总摊还代价给出总实际代价的一个上界;设法证明信用变化量始终>=0
势能法
对整个数据结构定义一个“势”函数$Phi$
定义一个操作的摊还代价为实际代价加上势的变化量
那么摊还代价的总和,等于实际代价的总和,加上整个过程中势的变化量
如果“整个过程中势的变化量”始终大于等于0,那么摊还代价的总和,给出了实际代价总和的一个上界
在实际代价难以计算的情况下,可以设计合适的势函数,使得每一次操作的摊还代价容易计算
(其实就是把“信用”的定义换到整个数据结构上来)
吉司机线段树:
https://codeforces.com/blog/entry/57319
实际上也不是就一定要用上面的方法..
里面好像是先分析对势函数的修改,得到势函数增长的上限,而对于extranode,访问一个节点就会减少1的势函数,势函数又始终>=0,因此得到extranode访问次数的上限;其余的访问次数的证明套用普通线段树区间操作即可
https://www.lydsy.com/JudgeOnline/problem.php?id=4695
每个节点维护区间最小值,次小值,最小值出现次数,最大值,次大值,最大值出现次数,区间和
(维护最小/大值出现次数,是为了方便在打上取min/取max标记同时,计算出对区间和的修改)
维护取min标记,取max标记,加法标记(加法标记优先级最低,前面两个要手动定义一个优先级)
然后用那篇cf帖子里面的方法做区间取min和区间取max操作,用普通线段树的方法做区间加法操作
pushdown的时候按照手工定义的三个操作的优先级进行
给节点加上标记时,细节很多,注意几个:
先考虑对数值的影响,再考虑对之前标记的影响
对数值的影响:
加法操作:就是最(次)大(小)值都要加上这个数,也要对应修改区间和;
取min/max操作:如果区间只有一种值或两种值,显然需要特判(就是打取min标记也要修改最小/次小值,打取max标记也要修改最大/次大值);打取min标记肯定要修改最大/次大值,打取max标记肯定要修改最小/次小值,肯定要对应修改区间和(具体方法:充分发扬人类智慧???就是说乱搞一下,能搞的)
对之前标记的影响:举例:设优先级:取min标记>取max标记>加法标记
要打取min/max标记了(设与x取min/max),如果之前有过加法标记(设加y),为了按照这个优先级的顺序做操作能得出正确结果,实际应该打上的标记是x-y;如果之前有过同样类型的标记,显然要对应取一下min/max
要打取min标记了(与x取min),如果之前有过取max标记(与y取max),且x<y,那么数就是先变到(y)再变到小(x),要让这个取max标记也变为x
pushup的细节也很多。。
upd:以下所有代码tag_condition都要变成(l==r)||(原内容),pushdown都要加一句if(l==r)return;虽然因为某些原因没有出锅,但是最好还是加上以防万一(其实是另一个题出了锅)
1 #pragma GCC optimize(3) 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 int a[500100]; 15 namespace S 16 { 17 const int mininf=-0x7fffffff; 18 const int maxinf=0x7fffffff; 19 #define N 1050000 20 #define lc (num<<1) 21 #define rc (num<<1|1) 22 struct I 23 { 24 int min1,min2,min1cnt; 25 int max1,max2,max1cnt; 26 ll sum; 27 }; 28 I operator+(const I &a,const I &b) 29 { 30 I ans;ans.sum=a.sum+b.sum; 31 if(a.min1<b.min1) 32 { 33 ans.min1=a.min1;ans.min1cnt=a.min1cnt; 34 ans.min2=min(a.min2,b.min1); 35 } 36 else if(a.min1>b.min1) 37 { 38 ans.min1=b.min1;ans.min1cnt=b.min1cnt; 39 ans.min2=min(b.min2,a.min1); 40 } 41 else 42 { 43 ans.min1=a.min1;ans.min1cnt=a.min1cnt+b.min1cnt; 44 ans.min2=min(a.min2,b.min2); 45 } 46 if(a.max1>b.max1) 47 { 48 ans.max1=a.max1;ans.max1cnt=a.max1cnt; 49 ans.max2=max(a.max2,b.max1); 50 } 51 else if(a.max1<b.max1) 52 { 53 ans.max1=b.max1;ans.max1cnt=b.max1cnt; 54 ans.max2=max(b.max2,a.max1); 55 } 56 else 57 { 58 ans.max1=a.max1;ans.max1cnt=a.max1cnt+b.max1cnt; 59 ans.max2=max(a.max2,b.max2); 60 } 61 return ans; 62 } 63 I d[N]; 64 int minv[N],maxv[N],addv[N]; 65 bool setmin[N],setmax[N]; 66 //规定标记:先取min,再取max,再加 67 void putMax(int x,int l,int r,int num) 68 //要求min1<x<min2 69 //先考虑对数值的影响,再考虑对标记的影响 70 { 71 if(d[num].min1>=x) return; 72 //assert(x<d[num].min2); 73 //if(setmax[num]&&x-addv[num]<maxv[num]) return; 74 if(d[num].min2==maxinf) d[num].max1=x; 75 else if(d[num].min1==d[num].max2) d[num].max2=x; 76 d[num].sum+=ll(d[num].min1cnt)*(x-d[num].min1); 77 d[num].min1=x; 78 if(!setmax[num]) setmax[num]=1,maxv[num]=x-addv[num]; 79 else maxv[num]=max(maxv[num],x-addv[num]); 80 } 81 void putMin(int x,int l,int r,int num) 82 { 83 if(d[num].max1<=x) return; 84 //assert(x>d[num].max2); 85 //if(setmin[num]&&x-addv[num]>minv[num]) return; 86 if(d[num].max2==mininf) d[num].min1=x; 87 else if(d[num].max1==d[num].min2) d[num].min2=x; 88 d[num].sum-=ll(d[num].max1cnt)*(d[num].max1-x); 89 d[num].max1=x; 90 /* 91 if(d[num].max2==mininf) 92 { 93 if(setmax[num]) 94 { 95 if(maxv[num]>x) 96 { 97 d[num].min1=x; 98 setmax[num]=0; 99 } 100 } 101 else 102 d[num].min1=x; 103 } 104 else if(d[num].max1==d[num].min2) 105 { 106 if(setmax[num]) 107 { 108 if(maxv[num]<x) d[num].min2=x; 109 else 110 { 111 d[num].min1=d[num].max1=x; 112 d[num].min2=maxinf;d[num].max2=mininf; 113 d[num].min1cnt=d[num].max1cnt=r-l+1; 114 setmax[num]=0; 115 } 116 } 117 else 118 d[num].min2=x; 119 } 120 */ 121 if(setmax[num]&&maxv[num]>x-addv[num]) maxv[num]=x-addv[num]; 122 if(!setmin[num]) setmin[num]=1,minv[num]=x-addv[num]; 123 else minv[num]=min(minv[num],x-addv[num]); 124 } 125 void doAdd(int x,int l,int r,int num) 126 { 127 d[num].sum+=ll(x)*(r-l+1); 128 d[num].min1+=x;d[num].max1+=x; 129 if(d[num].min2!=maxinf) d[num].min2+=x; 130 if(d[num].max2!=mininf) d[num].max2+=x; 131 addv[num]+=x; 132 } 133 void pd(int l,int r,int num) 134 { 135 int mid=l+((r-l)>>1); 136 if(setmin[num]) 137 { 138 putMin(minv[num],l,mid,lc); 139 putMin(minv[num],mid+1,r,rc); 140 setmin[num]=0; 141 } 142 if(setmax[num]) 143 { 144 putMax(maxv[num],l,mid,lc); 145 putMax(maxv[num],mid+1,r,rc); 146 setmax[num]=0; 147 } 148 if(addv[num]) 149 { 150 doAdd(addv[num],l,mid,lc); 151 doAdd(addv[num],mid+1,r,rc); 152 addv[num]=0; 153 } 154 } 155 void build(int l,int r,int num) 156 { 157 if(l==r) 158 { 159 d[num].max1=d[num].min1=d[num].sum=a[l]; 160 d[num].max2=mininf;d[num].min2=maxinf; 161 d[num].max1cnt=d[num].min1cnt=1; 162 return; 163 } 164 int mid=l+((r-l)>>1); 165 build(l,mid,lc);build(mid+1,r,rc); 166 d[num]=d[lc]+d[rc]; 167 } 168 void cmin(int L,int R,int x,int l,int r,int num) 169 { 170 if((r<L||R<l)||(d[num].max1<=x)) return; 171 if((L<=l&&r<=R)&&(d[num].max2<x&&x<d[num].max1)) 172 { 173 putMin(x,l,r,num); 174 return; 175 } 176 pd(l,r,num); 177 int mid=l+((r-l)>>1); 178 cmin(L,R,x,l,mid,lc); 179 cmin(L,R,x,mid+1,r,rc); 180 d[num]=d[lc]+d[rc]; 181 } 182 void cmax(int L,int R,int x,int l,int r,int num) 183 { 184 if((r<L||R<l)||(d[num].min1>=x)) return; 185 if((L<=l&&r<=R)&&(d[num].min2>x&&x>d[num].min1)) 186 { 187 putMax(x,l,r,num); 188 return; 189 } 190 pd(l,r,num); 191 int mid=l+((r-l)>>1); 192 cmax(L,R,x,l,mid,lc); 193 cmax(L,R,x,mid+1,r,rc); 194 d[num]=d[lc]+d[rc]; 195 } 196 void cadd(int L,int R,int x,int l,int r,int num) 197 { 198 if((r<L||R<l)) return; 199 if((L<=l&&r<=R)) 200 { 201 doAdd(x,l,r,num); 202 return; 203 } 204 pd(l,r,num); 205 int mid=l+((r-l)>>1); 206 cadd(L,R,x,l,mid,lc); 207 cadd(L,R,x,mid+1,r,rc); 208 d[num]=d[lc]+d[rc]; 209 } 210 I gett(int L,int R,int l,int r,int num) 211 { 212 if(L<=l&&r<=R) return d[num]; 213 pd(l,r,num); 214 int mid=l+((r-l)>>1); 215 if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+1,r,rc); 216 else if(L<=mid) return gett(L,R,l,mid,lc); 217 else if(mid<R) return gett(L,R,mid+1,r,rc); 218 else exit(-1); 219 } 220 #undef lc 221 #undef rc 222 } 223 int n,m; 224 int main() 225 { 226 int i,idx,l,r,x; 227 //freopen("/tmp/4695/10.in","r",stdin); 228 //freopen("/tmp/4695/10.ans","w",stdout); 229 scanf("%d",&n); 230 for(i=1;i<=n;i++) scanf("%d",&a[i]); 231 S::build(1,n,1); 232 scanf("%d",&m); 233 for(i=1;i<=m;i++) 234 { 235 scanf("%d",&idx); 236 switch(idx) 237 { 238 case 1: 239 scanf("%d%d%d",&l,&r,&x); 240 S::cadd(l,r,x,1,n,1); 241 break; 242 case 2: 243 scanf("%d%d%d",&l,&r,&x); 244 S::cmax(l,r,x,1,n,1); 245 break; 246 case 3: 247 scanf("%d%d%d",&l,&r,&x); 248 S::cmin(l,r,x,1,n,1); 249 break; 250 case 4: 251 scanf("%d%d",&l,&r); 252 printf("%lld ",S::gett(l,r,1,n,1).sum); 253 break; 254 case 5: 255 scanf("%d%d",&l,&r); 256 printf("%d ",S::gett(l,r,1,n,1).max1); 257 break; 258 case 6: 259 scanf("%d%d",&l,&r); 260 printf("%d ",S::gett(l,r,1,n,1).min1); 261 break; 262 } 263 } 264 return 0; 265 }
https://vjudge.net/problem/HDU-5306
1 #pragma GCC optimize(3) 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 int a[1000100]; 15 namespace S 16 { 17 const int mininf=-0x7fffffff; 18 const int maxinf=0x7fffffff; 19 #define N 2100000 20 #define lc (num<<1) 21 #define rc (num<<1|1) 22 struct I 23 { 24 int min1,min2,min1cnt; 25 int max1,max2,max1cnt; 26 ll sum; 27 }; 28 I operator+(const I &a,const I &b) 29 { 30 I ans;ans.sum=a.sum+b.sum; 31 if(a.min1<b.min1) 32 { 33 ans.min1=a.min1;ans.min1cnt=a.min1cnt; 34 ans.min2=min(a.min2,b.min1); 35 } 36 else if(a.min1>b.min1) 37 { 38 ans.min1=b.min1;ans.min1cnt=b.min1cnt; 39 ans.min2=min(b.min2,a.min1); 40 } 41 else 42 { 43 ans.min1=a.min1;ans.min1cnt=a.min1cnt+b.min1cnt; 44 ans.min2=min(a.min2,b.min2); 45 } 46 if(a.max1>b.max1) 47 { 48 ans.max1=a.max1;ans.max1cnt=a.max1cnt; 49 ans.max2=max(a.max2,b.max1); 50 } 51 else if(a.max1<b.max1) 52 { 53 ans.max1=b.max1;ans.max1cnt=b.max1cnt; 54 ans.max2=max(b.max2,a.max1); 55 } 56 else 57 { 58 ans.max1=a.max1;ans.max1cnt=a.max1cnt+b.max1cnt; 59 ans.max2=max(a.max2,b.max2); 60 } 61 return ans; 62 } 63 I d[N]; 64 int minv[N],maxv[N],addv[N]; 65 bool setmin[N],setmax[N]; 66 //规定标记:先取min,再取max,再加 67 void putMax(int x,int l,int r,int num) 68 //要求min1<x<min2 69 //先考虑对数值的影响,再考虑对标记的影响 70 { 71 if(d[num].min1>=x) return; 72 //assert(x<d[num].min2); 73 //if(setmax[num]&&x-addv[num]<maxv[num]) return; 74 if(d[num].min2==maxinf) d[num].max1=x; 75 else if(d[num].min1==d[num].max2) d[num].max2=x; 76 d[num].sum+=ll(d[num].min1cnt)*(x-d[num].min1); 77 d[num].min1=x; 78 if(!setmax[num]) setmax[num]=1,maxv[num]=x-addv[num]; 79 else maxv[num]=max(maxv[num],x-addv[num]); 80 } 81 void putMin(int x,int l,int r,int num) 82 { 83 if(d[num].max1<=x) return; 84 //assert(x>d[num].max2); 85 //if(setmin[num]&&x-addv[num]>minv[num]) return; 86 if(d[num].max2==mininf) d[num].min1=x; 87 else if(d[num].max1==d[num].min2) d[num].min2=x; 88 d[num].sum-=ll(d[num].max1cnt)*(d[num].max1-x); 89 d[num].max1=x; 90 /* 91 if(d[num].max2==mininf) 92 { 93 if(setmax[num]) 94 { 95 if(maxv[num]>x) 96 { 97 d[num].min1=x; 98 setmax[num]=0; 99 } 100 } 101 else 102 d[num].min1=x; 103 } 104 else if(d[num].max1==d[num].min2) 105 { 106 if(setmax[num]) 107 { 108 if(maxv[num]<x) d[num].min2=x; 109 else 110 { 111 d[num].min1=d[num].max1=x; 112 d[num].min2=maxinf;d[num].max2=mininf; 113 d[num].min1cnt=d[num].max1cnt=r-l+1; 114 setmax[num]=0; 115 } 116 } 117 else 118 d[num].min2=x; 119 } 120 */ 121 if(setmax[num]&&maxv[num]>x-addv[num]) maxv[num]=x-addv[num]; 122 if(!setmin[num]) setmin[num]=1,minv[num]=x-addv[num]; 123 else minv[num]=min(minv[num],x-addv[num]); 124 } 125 void doAdd(int x,int l,int r,int num) 126 { 127 d[num].sum+=ll(x)*(r-l+1); 128 d[num].min1+=x;d[num].max1+=x; 129 if(d[num].min2!=maxinf) d[num].min2+=x; 130 if(d[num].max2!=mininf) d[num].max2+=x; 131 addv[num]+=x; 132 } 133 void pd(int l,int r,int num) 134 { 135 int mid=l+((r-l)>>1); 136 if(setmin[num]) 137 { 138 putMin(minv[num],l,mid,lc); 139 putMin(minv[num],mid+1,r,rc); 140 setmin[num]=0; 141 } 142 if(setmax[num]) 143 { 144 putMax(maxv[num],l,mid,lc); 145 putMax(maxv[num],mid+1,r,rc); 146 setmax[num]=0; 147 } 148 if(addv[num]) 149 { 150 doAdd(addv[num],l,mid,lc); 151 doAdd(addv[num],mid+1,r,rc); 152 addv[num]=0; 153 } 154 } 155 void build(int l,int r,int num) 156 { 157 setmin[num]=setmax[num]=0;addv[num]=0; 158 if(l==r) 159 { 160 d[num].max1=d[num].min1=d[num].sum=a[l]; 161 d[num].max2=mininf;d[num].min2=maxinf; 162 d[num].max1cnt=d[num].min1cnt=1; 163 return; 164 } 165 int mid=l+((r-l)>>1); 166 build(l,mid,lc);build(mid+1,r,rc); 167 d[num]=d[lc]+d[rc]; 168 } 169 void cmin(int L,int R,int x,int l,int r,int num) 170 { 171 if((r<L||R<l)||(d[num].max1<=x)) return; 172 if((L<=l&&r<=R)&&(d[num].max2<x&&x<d[num].max1)) 173 { 174 putMin(x,l,r,num); 175 return; 176 } 177 pd(l,r,num); 178 int mid=l+((r-l)>>1); 179 cmin(L,R,x,l,mid,lc); 180 cmin(L,R,x,mid+1,r,rc); 181 d[num]=d[lc]+d[rc]; 182 } 183 void cmax(int L,int R,int x,int l,int r,int num) 184 { 185 if((r<L||R<l)||(d[num].min1>=x)) return; 186 if((L<=l&&r<=R)&&(d[num].min2>x&&x>d[num].min1)) 187 { 188 putMax(x,l,r,num); 189 return; 190 } 191 pd(l,r,num); 192 int mid=l+((r-l)>>1); 193 cmax(L,R,x,l,mid,lc); 194 cmax(L,R,x,mid+1,r,rc); 195 d[num]=d[lc]+d[rc]; 196 } 197 void cadd(int L,int R,int x,int l,int r,int num) 198 { 199 if((r<L||R<l)) return; 200 if((L<=l&&r<=R)) 201 { 202 doAdd(x,l,r,num); 203 return; 204 } 205 pd(l,r,num); 206 int mid=l+((r-l)>>1); 207 cadd(L,R,x,l,mid,lc); 208 cadd(L,R,x,mid+1,r,rc); 209 d[num]=d[lc]+d[rc]; 210 } 211 I gett(int L,int R,int l,int r,int num) 212 { 213 if(L<=l&&r<=R) return d[num]; 214 pd(l,r,num); 215 int mid=l+((r-l)>>1); 216 if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+1,r,rc); 217 else if(L<=mid) return gett(L,R,l,mid,lc); 218 else if(mid<R) return gett(L,R,mid+1,r,rc); 219 else exit(-1); 220 } 221 #undef lc 222 #undef rc 223 } 224 int n,m; 225 int main() 226 { 227 int i,idx,l,r,x,T; 228 scanf("%d",&T); 229 while(T--){ 230 scanf("%d%d",&n,&m); 231 for(i=1;i<=n;i++) scanf("%d",&a[i]); 232 S::build(1,n,1); 233 for(i=1;i<=m;i++) 234 { 235 scanf("%d",&idx); 236 switch(idx) 237 { 238 case 0: 239 scanf("%d%d%d",&l,&r,&x); 240 S::cmin(l,r,x,1,n,1); 241 break; 242 case 1: 243 scanf("%d%d",&l,&r); 244 printf("%d ",S::gett(l,r,1,n,1).max1); 245 break; 246 case 2: 247 scanf("%d%d",&l,&r); 248 printf("%lld ",S::gett(l,r,1,n,1).sum); 249 break; 250 } 251 }} 252 return 0; 253 }
小B的序列
http://210.33.19.103/contest/888/problem/2
啧,貌似是原题https://www.lydsy.com/JudgeOnline/problem.php?id=5312
题意:区间取and,区间取or,区间最大值
对每一(二进制)位搞一个以上类型的线段树,那么修改操作相当于,对于某些位的线段树,区间对0取min或对1取max(对x取and就是x中为0的位对应线段树区间对0取min,对x取or就是x中为1的位对应线段树区间对1取max)
当然这样子直接搞不能维护最大值,可以把所有位绑在一起,只建一个线段树,就可以维护了
这样的话,当当前节点区间[l,r]被目标区间[L,R]完全包含时,如果存在一些操作位在这个区间有0也有1,那么必须要向下dfs;如果所有操作位在这个区间要么全0要么全1,那么就是说要么满足break_condition,要么满足tag_condition,但是这个不用细分,直接puttag就行了(可以发现效果不变的)
错误记录:81,97行没有搞清问题本质,强行区分break和tag,于是复杂度错掉,T飞
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<cassert> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 int a[200100]; 15 //int num1; 16 namespace S 17 { 18 const int N=530000; 19 const int all1=(1<<20)-1; 20 #define lc (num<<1) 21 #define rc (num<<1|1) 22 //#define flip(x) (all1&(~(x))) 23 #define flip(x) (all1^(x)) 24 int andv[N],orv[N],isall0[N],isall1[N],maxn[N]; 25 //先and,再or 26 void doOr(int x,int l,int r,int num) 27 { 28 //if((isall1[num]&x)==x) return; 29 maxn[num]|=x; 30 isall0[num]&=flip(x);isall1[num]|=x; 31 orv[num]|=x; 32 } 33 void doAnd(int x,int l,int r,int num) 34 { 35 //if((isall0[num]&flip(x))==flip(x)) return; 36 maxn[num]&=x; 37 isall1[num]&=x;isall0[num]|=flip(x); 38 andv[num]&=x;orv[num]&=x; 39 } 40 void pd(int l,int r,int num) 41 { 42 if(l==r) return; 43 int mid=l+((r-l)>>1); 44 if(andv[num]!=all1) 45 { 46 doAnd(andv[num],l,mid,lc); 47 doAnd(andv[num],mid+1,r,rc); 48 andv[num]=all1; 49 } 50 if(orv[num]) 51 { 52 doOr(orv[num],l,mid,lc); 53 doOr(orv[num],mid+1,r,rc); 54 orv[num]=0; 55 } 56 } 57 void upd(int l,int r,int num) 58 { 59 isall0[num]=isall0[lc]&isall0[rc]; 60 isall1[num]=isall1[lc]&isall1[rc]; 61 maxn[num]=max(maxn[lc],maxn[rc]); 62 } 63 void build(int l,int r,int num) 64 { 65 andv[num]=all1;orv[num]=0; 66 if(l==r) 67 { 68 isall0[num]=flip(a[l]); 69 isall1[num]=a[l]; 70 maxn[num]=a[l]; 71 return; 72 } 73 int mid=l+((r-l)>>1); 74 build(l,mid,lc);build(mid+1,r,rc); 75 upd(l,r,num); 76 } 77 void cor(int L,int R,int x,int l,int r,int num) 78 {//num1++; 79 if((r<L||R<l)) return; 80 //printf("or%d %d %d ",l,r,num); 81 if(l==r||((L<=l&&r<=R)&&(((isall0[num]&x)|(isall1[num]&x))==x))) 82 { 83 doOr(x,l,r,num); 84 return; 85 } 86 //if(l==r) return; 87 pd(l,r,num); 88 int mid=l+((r-l)>>1); 89 cor(L,R,x,l,mid,lc); 90 cor(L,R,x,mid+1,r,rc); 91 upd(l,r,num); 92 } 93 void cand(int L,int R,int x,int l,int r,int num) 94 {//num1++; 95 if((r<L||R<l)) return; 96 //printf("and%d %d %d ",l,r,num); 97 if(l==r||((L<=l&&r<=R)&&(((isall1[num]&flip(x))|(isall0[num]&flip(x)))==flip(x)))) 98 { 99 doAnd(x,l,r,num); 100 return; 101 } 102 //if(l==r) return; 103 pd(l,r,num); 104 int mid=l+((r-l)>>1); 105 cand(L,R,x,l,mid,lc); 106 cand(L,R,x,mid+1,r,rc); 107 upd(l,r,num); 108 } 109 int gmax(int L,int R,int l,int r,int num) 110 { 111 if(L<=l&&r<=R) return maxn[num]; 112 pd(l,r,num); 113 int mid=l+((r-l)>>1),ans=-1; 114 if(L<=mid) ans=max(ans,gmax(L,R,l,mid,lc)); 115 if(mid<R) ans=max(ans,gmax(L,R,mid+1,r,rc)); 116 return ans; 117 } 118 #undef lc 119 #undef rc 120 } 121 int n,q; 122 int main() 123 { 124 int i,idx,l,r,x; 125 scanf("%d%d",&n,&q); 126 for(i=1;i<=n;i++) scanf("%d",&a[i]); 127 S::build(1,n,1); 128 while(q--) 129 { 130 //int t=num1; 131 scanf("%d",&idx); 132 switch(idx) 133 { 134 case 1: 135 scanf("%d%d%d",&l,&r,&x); 136 S::cand(l,r,x,1,n,1); 137 break; 138 case 2: 139 scanf("%d%d%d",&l,&r,&x); 140 S::cor(l,r,x,1,n,1); 141 break; 142 case 3: 143 scanf("%d%d",&l,&r); 144 S::gmax(l,r,1,n,1); 145 printf("%d ",S::gmax(l,r,1,n,1)); 146 } 147 //if(num1-t>100000) printf("%d ",num1-t); 148 //if(q%1000==0)printf("test%d ",num1); 149 } 150 return 0; 151 }
https://www.lydsy.com/JudgeOnline/problem.php?id=4355
接着改板子。。。
错误记录:17行最大值不够大
1 #pragma GCC optimize(3) 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 ll a[500100]; 15 namespace S 16 { 17 const ll maxinf=0x7fffffffffffffff; 18 #define N 1050000 19 #define lc (num<<1) 20 #define rc (num<<1|1) 21 struct I 22 { 23 ll min1,min2,min1cnt; 24 }; 25 I operator+(const I &a,const I &b) 26 { 27 I ans; 28 if(a.min1<b.min1) 29 { 30 ans.min1=a.min1;ans.min1cnt=a.min1cnt; 31 ans.min2=min(a.min2,b.min1); 32 } 33 else if(a.min1>b.min1) 34 { 35 ans.min1=b.min1;ans.min1cnt=b.min1cnt; 36 ans.min2=min(b.min2,a.min1); 37 } 38 else 39 { 40 ans.min1=a.min1;ans.min1cnt=a.min1cnt+b.min1cnt; 41 ans.min2=min(a.min2,b.min2); 42 } 43 return ans; 44 } 45 I d[N]; 46 ll maxv[N],addv[N],setv[N]; 47 bool setmax[N],set[N]; 48 //规定标记:先赋值,再取max,再加 49 void putMax(ll x,int l,int r,int num) 50 //要求min1<x<min2 51 //先考虑对数值的影响,再考虑对标记的影响 52 { 53 if(d[num].min1>=x) return; 54 d[num].min1=x; 55 if(!setmax[num]) setmax[num]=1,maxv[num]=x-addv[num]; 56 else maxv[num]=max(maxv[num],x-addv[num]); 57 } 58 void doSet(ll x,int l,int r,int num) 59 { 60 d[num].min1=x;d[num].min2=maxinf;d[num].min1cnt=r-l+1; 61 setmax[num]=0;addv[num]=0; 62 set[num]=1;setv[num]=x; 63 } 64 void doAdd(ll x,int l,int r,int num) 65 { 66 d[num].min1+=x; 67 if(d[num].min2!=maxinf) d[num].min2+=x; 68 addv[num]+=x; 69 } 70 void pd(int l,int r,int num) 71 { 72 int mid=l+((r-l)>>1); 73 if(set[num]) 74 { 75 doSet(setv[num],l,mid,lc); 76 doSet(setv[num],mid+1,r,rc); 77 set[num]=0; 78 } 79 if(setmax[num]) 80 { 81 putMax(maxv[num],l,mid,lc); 82 putMax(maxv[num],mid+1,r,rc); 83 setmax[num]=0; 84 } 85 if(addv[num]) 86 { 87 doAdd(addv[num],l,mid,lc); 88 doAdd(addv[num],mid+1,r,rc); 89 addv[num]=0; 90 } 91 } 92 void build(int l,int r,int num) 93 { 94 if(l==r) 95 { 96 d[num].min1=a[l]; 97 d[num].min2=maxinf; 98 d[num].min1cnt=1; 99 return; 100 } 101 int mid=l+((r-l)>>1); 102 build(l,mid,lc);build(mid+1,r,rc); 103 d[num]=d[lc]+d[rc]; 104 } 105 void cmax(int L,int R,ll x,int l,int r,int num) 106 { 107 if((r<L||R<l)||(d[num].min1>=x)) return; 108 if((L<=l&&r<=R)&&(d[num].min2>x&&x>d[num].min1)) 109 { 110 putMax(x,l,r,num); 111 return; 112 } 113 pd(l,r,num); 114 int mid=l+((r-l)>>1); 115 cmax(L,R,x,l,mid,lc); 116 cmax(L,R,x,mid+1,r,rc); 117 d[num]=d[lc]+d[rc]; 118 } 119 void cadd(int L,int R,ll x,int l,int r,int num) 120 { 121 if((r<L||R<l)) return; 122 if((L<=l&&r<=R)) 123 { 124 doAdd(x,l,r,num); 125 return; 126 } 127 pd(l,r,num); 128 int mid=l+((r-l)>>1); 129 cadd(L,R,x,l,mid,lc); 130 cadd(L,R,x,mid+1,r,rc); 131 d[num]=d[lc]+d[rc]; 132 } 133 void cset(int L,int R,ll x,int l,int r,int num) 134 { 135 if((r<L||R<l)) return; 136 if((L<=l&&r<=R)) 137 { 138 doSet(x,l,r,num); 139 return; 140 } 141 pd(l,r,num); 142 int mid=l+((r-l)>>1); 143 cset(L,R,x,l,mid,lc); 144 cset(L,R,x,mid+1,r,rc); 145 d[num]=d[lc]+d[rc]; 146 } 147 I gett(int L,int R,int l,int r,int num) 148 { 149 if(L<=l&&r<=R) return d[num]; 150 pd(l,r,num); 151 int mid=l+((r-l)>>1); 152 if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+1,r,rc); 153 else if(L<=mid) return gett(L,R,l,mid,lc); 154 else if(mid<R) return gett(L,R,mid+1,r,rc); 155 else exit(-1); 156 } 157 #undef lc 158 #undef rc 159 } 160 int n,m; 161 int main() 162 { 163 int i,idx,l,r;ll x;S::I ttt; 164 //freopen("/tmp/4355/11.in","r",stdin); 165 //freopen("/tmp/4355/11.ans","w",stdout); 166 scanf("%d%d",&n,&m); 167 for(i=1;i<=n;i++) scanf("%lld",&a[i]); 168 S::build(1,n,1); 169 for(i=1;i<=m;i++) 170 { 171 scanf("%d",&idx); 172 switch(idx) 173 { 174 case 1: 175 scanf("%d%d%lld",&l,&r,&x); 176 S::cset(l,r,x,1,n,1); 177 break; 178 case 2: 179 scanf("%d%d%lld",&l,&r,&x); 180 S::cadd(l,r,x,1,n,1); 181 S::cmax(l,r,0,1,n,1); 182 break; 183 case 3: 184 scanf("%d%d",&l,&r); 185 ttt=S::gett(l,r,1,n,1); 186 printf("%lld ",ttt.min1==0?ttt.min1cnt:0); 187 } 188 } 189 return 0; 190 }