算导:

核算法

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

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

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

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

如果信用变化量始终>=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[];
  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]=,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]=,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+);
  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)>>);
  136. if(setmin[num])
  137. {
  138. putMin(minv[num],l,mid,lc);
  139. putMin(minv[num],mid+,r,rc);
  140. setmin[num]=;
  141. }
  142. if(setmax[num])
  143. {
  144. putMax(maxv[num],l,mid,lc);
  145. putMax(maxv[num],mid+,r,rc);
  146. setmax[num]=;
  147. }
  148. if(addv[num])
  149. {
  150. doAdd(addv[num],l,mid,lc);
  151. doAdd(addv[num],mid+,r,rc);
  152. addv[num]=;
  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=;
  162. return;
  163. }
  164. int mid=l+((r-l)>>);
  165. build(l,mid,lc);build(mid+,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)>>);
  178. cmin(L,R,x,l,mid,lc);
  179. cmin(L,R,x,mid+,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)>>);
  192. cmax(L,R,x,l,mid,lc);
  193. cmax(L,R,x,mid+,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)>>);
  206. cadd(L,R,x,l,mid,lc);
  207. cadd(L,R,x,mid+,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)>>);
  215. if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+,r,rc);
  216. else if(L<=mid) return gett(L,R,l,mid,lc);
  217. else if(mid<R) return gett(L,R,mid+,r,rc);
  218. else exit(-);
  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=;i<=n;i++) scanf("%d",&a[i]);
  231. S::build(,n,);
  232. scanf("%d",&m);
  233. for(i=;i<=m;i++)
  234. {
  235. scanf("%d",&idx);
  236. switch(idx)
  237. {
  238. case :
  239. scanf("%d%d%d",&l,&r,&x);
  240. S::cadd(l,r,x,,n,);
  241. break;
  242. case :
  243. scanf("%d%d%d",&l,&r,&x);
  244. S::cmax(l,r,x,,n,);
  245. break;
  246. case :
  247. scanf("%d%d%d",&l,&r,&x);
  248. S::cmin(l,r,x,,n,);
  249. break;
  250. case :
  251. scanf("%d%d",&l,&r);
  252. printf("%lld\n",S::gett(l,r,,n,).sum);
  253. break;
  254. case :
  255. scanf("%d%d",&l,&r);
  256. printf("%d\n",S::gett(l,r,,n,).max1);
  257. break;
  258. case :
  259. scanf("%d%d",&l,&r);
  260. printf("%d\n",S::gett(l,r,,n,).min1);
  261. break;
  262. }
  263. }
  264. return ;
  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[];
  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]=,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]=,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+);
  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)>>);
  136. if(setmin[num])
  137. {
  138. putMin(minv[num],l,mid,lc);
  139. putMin(minv[num],mid+,r,rc);
  140. setmin[num]=;
  141. }
  142. if(setmax[num])
  143. {
  144. putMax(maxv[num],l,mid,lc);
  145. putMax(maxv[num],mid+,r,rc);
  146. setmax[num]=;
  147. }
  148. if(addv[num])
  149. {
  150. doAdd(addv[num],l,mid,lc);
  151. doAdd(addv[num],mid+,r,rc);
  152. addv[num]=;
  153. }
  154. }
  155. void build(int l,int r,int num)
  156. {
  157. setmin[num]=setmax[num]=;addv[num]=;
  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=;
  163. return;
  164. }
  165. int mid=l+((r-l)>>);
  166. build(l,mid,lc);build(mid+,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)>>);
  179. cmin(L,R,x,l,mid,lc);
  180. cmin(L,R,x,mid+,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)>>);
  193. cmax(L,R,x,l,mid,lc);
  194. cmax(L,R,x,mid+,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)>>);
  207. cadd(L,R,x,l,mid,lc);
  208. cadd(L,R,x,mid+,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)>>);
  216. if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+,r,rc);
  217. else if(L<=mid) return gett(L,R,l,mid,lc);
  218. else if(mid<R) return gett(L,R,mid+,r,rc);
  219. else exit(-);
  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=;i<=n;i++) scanf("%d",&a[i]);
  232. S::build(,n,);
  233. for(i=;i<=m;i++)
  234. {
  235. scanf("%d",&idx);
  236. switch(idx)
  237. {
  238. case :
  239. scanf("%d%d%d",&l,&r,&x);
  240. S::cmin(l,r,x,,n,);
  241. break;
  242. case :
  243. scanf("%d%d",&l,&r);
  244. printf("%d\n",S::gett(l,r,,n,).max1);
  245. break;
  246. case :
  247. scanf("%d%d",&l,&r);
  248. printf("%lld\n",S::gett(l,r,,n,).sum);
  249. break;
  250. }
  251. }}
  252. return ;
  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[];
  15. //int num1;
  16. namespace S
  17. {
  18. const int N=;
  19. const int all1=(<<)-;
  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)>>);
  44. if(andv[num]!=all1)
  45. {
  46. doAnd(andv[num],l,mid,lc);
  47. doAnd(andv[num],mid+,r,rc);
  48. andv[num]=all1;
  49. }
  50. if(orv[num])
  51. {
  52. doOr(orv[num],l,mid,lc);
  53. doOr(orv[num],mid+,r,rc);
  54. orv[num]=;
  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]=;
  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)>>);
  74. build(l,mid,lc);build(mid+,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)>>);
  89. cor(L,R,x,l,mid,lc);
  90. cor(L,R,x,mid+,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)>>);
  105. cand(L,R,x,l,mid,lc);
  106. cand(L,R,x,mid+,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)>>),ans=-;
  114. if(L<=mid) ans=max(ans,gmax(L,R,l,mid,lc));
  115. if(mid<R) ans=max(ans,gmax(L,R,mid+,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=;i<=n;i++) scanf("%d",&a[i]);
  127. S::build(,n,);
  128. while(q--)
  129. {
  130. //int t=num1;
  131. scanf("%d",&idx);
  132. switch(idx)
  133. {
  134. case :
  135. scanf("%d%d%d",&l,&r,&x);
  136. S::cand(l,r,x,,n,);
  137. break;
  138. case :
  139. scanf("%d%d%d",&l,&r,&x);
  140. S::cor(l,r,x,,n,);
  141. break;
  142. case :
  143. scanf("%d%d",&l,&r);
  144. S::gmax(l,r,,n,);
  145. printf("%d\n",S::gmax(l,r,,n,));
  146. }
  147. //if(num1-t>100000) printf("%d\n",num1-t);
  148. //if(q%1000==0)printf("test%d\n",num1);
  149. }
  150. return ;
  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[];
  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]=,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+;
  61. setmax[num]=;addv[num]=;
  62. set[num]=;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)>>);
  73. if(set[num])
  74. {
  75. doSet(setv[num],l,mid,lc);
  76. doSet(setv[num],mid+,r,rc);
  77. set[num]=;
  78. }
  79. if(setmax[num])
  80. {
  81. putMax(maxv[num],l,mid,lc);
  82. putMax(maxv[num],mid+,r,rc);
  83. setmax[num]=;
  84. }
  85. if(addv[num])
  86. {
  87. doAdd(addv[num],l,mid,lc);
  88. doAdd(addv[num],mid+,r,rc);
  89. addv[num]=;
  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=;
  99. return;
  100. }
  101. int mid=l+((r-l)>>);
  102. build(l,mid,lc);build(mid+,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)>>);
  115. cmax(L,R,x,l,mid,lc);
  116. cmax(L,R,x,mid+,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)>>);
  129. cadd(L,R,x,l,mid,lc);
  130. cadd(L,R,x,mid+,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)>>);
  143. cset(L,R,x,l,mid,lc);
  144. cset(L,R,x,mid+,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)>>);
  152. if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+,r,rc);
  153. else if(L<=mid) return gett(L,R,l,mid,lc);
  154. else if(mid<R) return gett(L,R,mid+,r,rc);
  155. else exit(-);
  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=;i<=n;i++) scanf("%lld",&a[i]);
  168. S::build(,n,);
  169. for(i=;i<=m;i++)
  170. {
  171. scanf("%d",&idx);
  172. switch(idx)
  173. {
  174. case :
  175. scanf("%d%d%lld",&l,&r,&x);
  176. S::cset(l,r,x,,n,);
  177. break;
  178. case :
  179. scanf("%d%d%lld",&l,&r,&x);
  180. S::cadd(l,r,x,,n,);
  181. S::cmax(l,r,,,n,);
  182. break;
  183. case :
  184. scanf("%d%d",&l,&r);
  185. ttt=S::gett(l,r,,n,);
  186. printf("%lld\n",ttt.min1==?ttt.min1cnt:);
  187. }
  188. }
  189. return ;
  190. }

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

  1. bzoj 4695 最假女选手 吉利线段树

    最假女选手 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 480  Solved: 118[Submit][Status][Discuss] Desc ...

  2. BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

    题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...

  3. bzoj 4695: 最假女选手

    ……一道丧病线段树膜板题…… 被常数卡的死去活来……QAQ 学到了些奇技淫巧:把取min标记 和 区间最小值 合并 可以快很多…… #include <bits/stdc++.h> #de ...

  4. BZOJ 4695 最假女选手 线段树

    题意: 给定一个长度为 N序列,编号从1 到 N.要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x  2.把一个区间[L,R] 里小于x 的数变成x  3.把一个区间[L,R] 里大于x ...

  5. BZOJ4695 最假女选手(势能线段树)

    BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...

  6. bzoj4695 最假女选手

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4695 [题解] SegmentTree beats!(见jiry_2论文/营员交流) 考虑只 ...

  7. BZOJ4695:最假女选手

    浅谈区间最值操作和历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html 题目传送门:https://lydsy.com/JudgeOnline/pr ...

  8. 2018.07.27 bzoj4695: 最假女选手(线段树)

    传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...

  9. 【bzoj4695】最假女选手 线段树区间最值操作

    题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...

随机推荐

  1. POJ 1088 滑雪 ( DFS+动态规划思想 )

    滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 79519   Accepted: 29581 Description ...

  2. 学习c编程的第二天

    函数又叫方法,是实现某项功能或完成某项任务的代码块 #include<stdio.h>void show(){ printf("I like c language"); ...

  3. 纯属娱乐,对入门Android有一定的帮助

    package android.m9;   import android.app.Activity; import android.os.Bundle; import android.view.Men ...

  4. Service的两种启动方式

    今天又写Service,提示覆写onBind(),想起Android好像是有个叫做Binder的IPC机制. Service里面有一个onBind(),一个onStartCommand(),两者都能启 ...

  5. POJ 3104 Contestants Division

    Contestants Division Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10597   Accepted:  ...

  6. 十五、事务(Transaction)

    1.事务是什么? 2.示例 查询事务的隔离级别, 1>会话级(select @@tx_isolation或select @@session.tx_isolation) 2>全局级(sele ...

  7. codeforces 813C The Tag Game 树+dfs追击问题

    C. The Tag Gametime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutpu ...

  8. oracle创建用户空间、导出、导入dmp备份文件方法

    导入数据需要注意的事项 1.创建一个用户对应一个表空间. 2.创建的用户和表空间一定要与bmp文件的用户和表空间一致. 3.导入的命令是在CMD下输入的 不是在SQL plus输入的. 4.可以用PL ...

  9. SQL Server服务器连接配置

    一.首先确保服务器能在本地打开数据库 如果碰到本地无法连接到数据库,首先要确认上图中两个服务是否开启 二.其次,要配置远端可连接的用户 如图,配置数据库[属性]中[安全性]为混合验证,勾中允许远程连接 ...

  10. LeetCode: 412 Fizz Buzz(easy)

    题目: Write a program that outputs the string representation of numbers from 1 to n. But for multiples ...