bzoj 4695: 最假女选手 && Gorgeous Sequence HDU - 5306 && (bzoj5312 冒险 || 小B的序列) && bzoj4355: Play with sequence

算导:

核算法

给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量。

当实际代价小于摊还代价时,增加等于差额的信用;

当实际代价大于摊还代价时,减少等于差额的信用。

显然总摊还代价等于总实际代价+总信用变化量。

如果信用变化量始终>=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\n",S::gett(l,r,1,n,1).sum);
253             break;
254         case 5:
255             scanf("%d%d",&l,&r);
256             printf("%d\n",S::gett(l,r,1,n,1).max1);
257             break;
258         case 6:
259             scanf("%d%d",&l,&r);
260             printf("%d\n",S::gett(l,r,1,n,1).min1);
261             break;
262         }
263     }
264     return 0;
265 }
View Code

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\n",S::gett(l,r,1,n,1).max1);
245             break;
246         case 2:
247             scanf("%d%d",&l,&r);
248             printf("%lld\n",S::gett(l,r,1,n,1).sum);
249             break;
250         }
251     }}
252     return 0;
253 }
View Code

小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\n",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\n",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\n",S::gmax(l,r,1,n,1));
146         }
147         //if(num1-t>100000)  printf("%d\n",num1-t);
148         //if(q%1000==0)printf("test%d\n",num1);
149     }
150     return 0;
151 }
View Code

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\n",ttt.min1==0?ttt.min1cnt:0);
187         }
188     }
189     return 0;
190 }
View Code

 

posted @ 2018-08-06 14:34  hehe_54321  阅读(387)  评论(0编辑  收藏  举报
AmazingCounters.com