[关闭]
@xiaoziyao 2021-08-19T04:27:48.000000Z 字数 7296 阅读 683

P7825 「RdOI R3」VSQ 解题报告

解题报告


P7825 「RdOI R3」VSQ解题报告:

更好的阅读体验

题意

给定一个长度为 的 01 序列,共 次操作,每次支持区间推平,区间反转,查询区间最长 间隔串,查询区间长度为 间隔串数量。

分析

为什么我要做这种毒瘤 ds 题啊,毒瘤 ds 毁我一上午。

首先套路地进行差分,那么我们要进行的操作就变成了:支持序列 的区间推平,异或,支持 的差分序列 的区间推平为 和单点修改,以及查询 的区间最长全 段和区间长度大于等于 的全 段数。

除了最后一个操作都可以用两颗线段树套路地维护,考虑最后一个操作怎么维护,考场我想的是分块,发现复杂度完全不能接受,于是写了写珂朵莉树,发现也不行,就罚坐到比赛结束。/ll

实际上可以考虑用第二棵线段树同时维护每个线段树区间的所有全 段,每次区间推平为 就在每个结点暴力删除全 段,单点修改就在对应的结点用珂朵莉树类似的写法合并与分裂区间,然后每个区间的长度扔到对应结点的树状数组里,每次查询记一下上个位置,然后在树状数组内查一查,分类讨论一下就可以做了。

时间复杂度:

代码

  1. #include<stdio.h>
  2. #include<math.h>
  3. #include<vector>
  4. #include<set>
  5. #define lc(x) (x)<<1
  6. #define rc(x) (x)<<1|1
  7. #define lowbit(x) x&-x
  8. using namespace std;
  9. const int maxn=500005,maxm=500005,maxt=maxn<<2;
  10. int n,m;
  11. int a[maxn],b[maxn],qo[maxm],ql[maxm],qr[maxm],qk[maxm],tag[maxt],lazy[maxt];
  12. void abuild(int l,int r,int now){
  13. lazy[now]=-1;
  14. if(l==r){
  15. lazy[now]=a[l];
  16. return ;
  17. }
  18. int mid=(l+r)>>1;
  19. abuild(l,mid,lc(now)),abuild(mid+1,r,rc(now));
  20. }
  21. inline void agetlazy(int now,int v){
  22. lazy[now]=v,tag[now]=0;
  23. }
  24. inline void agettag(int now){
  25. if(lazy[now]!=-1)
  26. lazy[now]^=1;
  27. else tag[now]^=1;
  28. }
  29. inline void apushdown(int now){
  30. if(tag[now])
  31. agettag(lc(now)),agettag(rc(now)),tag[now]=0;
  32. if(lazy[now]!=-1)
  33. agetlazy(lc(now),lazy[now]),agetlazy(rc(now),lazy[now]),lazy[now]=-1;
  34. }
  35. void aupdate(int l,int r,int now,int L,int R,int v){
  36. if(L<=l&&r<=R){
  37. agetlazy(now,v);
  38. return ;
  39. }
  40. int mid=(l+r)>>1;
  41. apushdown(now);
  42. if(L<=mid)
  43. aupdate(l,mid,lc(now),L,R,v);
  44. if(mid<R)
  45. aupdate(mid+1,r,rc(now),L,R,v);
  46. }
  47. void aupdatexor(int l,int r,int now,int L,int R){
  48. if(L<=l&&r<=R){
  49. agettag(now);
  50. return ;
  51. }
  52. int mid=(l+r)>>1;
  53. apushdown(now);
  54. if(L<=mid)
  55. aupdatexor(l,mid,lc(now),L,R);
  56. if(mid<R)
  57. aupdatexor(mid+1,r,rc(now),L,R);
  58. }
  59. int aquery(int l,int r,int now,int pos){
  60. if(l==r)
  61. return tag[now]^lazy[now];
  62. apushdown(now);
  63. int mid=(l+r)>>1;
  64. return pos<=mid? aquery(l,mid,lc(now),pos):aquery(mid+1,r,rc(now),pos);
  65. }
  66. vector<int>t1[maxt],t2[maxt];
  67. void update(int now,int pos,int val){
  68. if(pos==1)
  69. return ;
  70. int len=t1[now].size()-1;
  71. for(int i=len-pos+1;i<=len;i+=lowbit(i))
  72. t1[now][i]+=val,t2[now][i]+=val*pos;
  73. }
  74. int query(int now,int pos){
  75. if(pos==1)
  76. return 0;
  77. int len=t1[now].size()-1,res=0;
  78. if(len<pos)
  79. return 0;
  80. for(int i=len-pos+1;i;i-=lowbit(i))
  81. res+=t2[now][i]-t1[now][i]*(pos-1);
  82. return res;
  83. }
  84. int blazy[maxt];
  85. struct bnode{
  86. int pre,suf,maxx,len;
  87. }t[maxt];
  88. struct section{
  89. int l,r;
  90. bool operator < (const section &p)const{
  91. return l<p.l;
  92. }
  93. }lst;
  94. set<section>s[maxt];
  95. void cmodify(int now,int x,int v){
  96. // printf("cmodify %d (%d,%d)\n",now,x,v);
  97. if(v==1){
  98. if(s[now].empty()){
  99. s[now].insert(section{x,x}),update(now,1,1);
  100. return ;
  101. }
  102. set<section>::iterator itr=s[now].upper_bound(section{x,-1}),itl=itr;
  103. itl--;
  104. int l=itl->l,r=itr->r;
  105. int lt=itr!=s[now].begin()&&itl->r==x-1,rt=itr!=s[now].end()&&itr->l==x+1;
  106. if(lt==0&&rt==0)
  107. s[now].insert(section{x,x}),update(now,1,1);
  108. if(lt==1&&rt==0)
  109. s[now].erase(itl),update(now,x-l,-1),s[now].insert(section{l,x}),update(now,x-l+1,1);
  110. if(lt==0&&rt==1)
  111. s[now].erase(itr),update(now,r-x,-1),s[now].insert(section{x,r}),update(now,r-x+1,1);
  112. if(lt==1&&rt==1)
  113. s[now].erase(itl),update(now,x-l,-1),s[now].erase(itr),update(now,r-x,-1),s[now].insert(section{l,r}),update(now,r-l+1,1);
  114. }
  115. if(v==0){
  116. set<section>::iterator it=s[now].upper_bound(section{x,-1});
  117. it--;
  118. int l=it->l,r=it->r;
  119. s[now].erase(it),update(now,r-l+1,-1);
  120. if(l==x&&r!=x)
  121. s[now].insert(section{l+1,r}),update(now,r-l,1);
  122. if(l!=x&&r==x)
  123. s[now].insert(section{l,r-1}),update(now,r-l,1);
  124. if(l!=x&&r!=x)
  125. s[now].insert(section{l,x-1}),update(now,x-l,1),s[now].insert(section{x+1,r}),update(now,r-x,1);
  126. }
  127. }
  128. set<section>::iterator split(int now,int pos){
  129. set<section>::iterator it=s[now].lower_bound(section{pos,-1}),tmp=it;
  130. if(it!=s[now].end()&&(it==s[now].begin()||it->l==pos))
  131. return it;
  132. tmp--;
  133. if(tmp->r<pos)
  134. return it;
  135. int l=tmp->l,r=tmp->r;
  136. s[now].erase(tmp),update(now,r-l+1,-1);
  137. if(pos>l)
  138. s[now].insert(section{l,pos-1}),update(now,pos-l,1);
  139. update(now,r-pos+1,1);
  140. return s[now].insert(section{pos,r}).first;
  141. }
  142. bnode merge(bnode a,bnode b){
  143. bnode res;
  144. res.pre=a.len==a.pre? (a.len+b.pre):a.pre;
  145. res.suf=b.len==b.suf? (b.len+a.suf):b.suf;
  146. res.maxx=max(max(a.maxx,b.maxx),a.suf+b.pre);
  147. res.len=a.len+b.len;
  148. return res;
  149. }
  150. inline void bpushup(int now){
  151. t[now]=merge(t[lc(now)],t[rc(now)]);
  152. }
  153. void bbuild(int l,int r,int now){
  154. // printf("l=%d r=%d now=%d\n",l,r,now);
  155. t1[now].resize(r-l+2),t2[now].resize(r-l+2);
  156. for(int i=l;i<=r;i++)
  157. if(b[i])
  158. cmodify(now,i,1);
  159. if(l==r){
  160. t[now].len=1,t[now].pre=t[now].suf=t[now].maxx=b[l];
  161. return ;
  162. }
  163. int mid=(l+r)>>1;
  164. bbuild(l,mid,lc(now)),bbuild(mid+1,r,rc(now));
  165. bpushup(now);
  166. }
  167. inline void bgetlazy(int now){
  168. t[now].pre=t[now].suf=t[now].maxx=0,blazy[now]=1;
  169. }
  170. inline void bpushdown(int now){
  171. if(blazy[now])
  172. bgetlazy(lc(now)),bgetlazy(rc(now)),blazy[now]=0;
  173. }
  174. void bmodify(int l,int r,int now,int pos,int v){
  175. cmodify(now,pos,v);
  176. if(l==r){
  177. b[l]=t[now].pre=t[now].suf=t[now].maxx=v;
  178. return ;
  179. }
  180. int mid=(l+r)>>1;
  181. bpushdown(now);
  182. if(pos<=mid)
  183. bmodify(l,mid,lc(now),pos,v);
  184. else bmodify(mid+1,r,rc(now),pos,v);
  185. bpushup(now);
  186. }
  187. void bupdate(int l,int r,int now,int L,int R){
  188. if(L<=l&&r<=R){
  189. bgetlazy(now);
  190. return ;
  191. }
  192. int mid=(l+r)>>1;
  193. bpushdown(now);
  194. if(L<=mid)
  195. bupdate(l,mid,lc(now),L,R);
  196. if(mid<R)
  197. bupdate(mid+1,r,rc(now),L,R);
  198. bpushup(now);
  199. }
  200. void cupdate(int l,int r,int now,int L,int R){
  201. if(s[now].size()==0)
  202. return ;
  203. if(l==r){
  204. for(set<section>::iterator it=s[now].begin();it!=s[now].end();it=s[now].erase(it))
  205. update(now,it->r-it->l+1,-1);
  206. return ;
  207. }
  208. set<section>::iterator itr=split(now,min(r,R)+1),itl=split(now,max(l,L));
  209. while(itl!=itr)
  210. update(now,itl->r-itl->l+1,-1),itl=s[now].erase(itl);
  211. int mid=(l+r)>>1;
  212. if(L<=mid)
  213. cupdate(l,mid,lc(now),L,R);
  214. if(mid<R)
  215. cupdate(mid+1,r,rc(now),L,R);
  216. }
  217. int bget(int l,int r,int now,int pos){
  218. if(l==r)
  219. return t[now].maxx;
  220. int mid=(l+r)>>1;
  221. bpushdown(now);
  222. return pos<=mid? bget(l,mid,lc(now),pos):bget(mid+1,r,rc(now),pos);
  223. }
  224. int bquerysum(int l,int r,int now,int L,int R,int K){
  225. if(s[now].empty())
  226. return 0;
  227. if(L<=l&&r<=R){
  228. int res=query(now,K);
  229. section st=*s[now].begin(),ed=*s[now].rbegin();
  230. if(lst.r+1==st.l){
  231. res+=max(st.r-lst.l+1-K+1,0)-max(lst.r-lst.l+1-K+1,0)-max(st.r-st.l+1-K+1,0);
  232. if(s[now].size()==1)
  233. lst=section{lst.l,ed.r};
  234. else lst=ed;
  235. }
  236. else lst=ed;
  237. return res;
  238. }
  239. int mid=(l+r)>>1,res=0;
  240. if(L<=mid)
  241. res+=bquerysum(l,mid,lc(now),L,R,K);
  242. if(mid<R)
  243. res+=bquerysum(mid+1,r,rc(now),L,R,K);
  244. return res;
  245. }
  246. bnode bquerymax(int l,int r,int now,int L,int R){
  247. if(L<=l&&r<=R)
  248. return t[now];
  249. int mid=(l+r)>>1;
  250. bpushdown(now);
  251. if(L<=mid&&mid<R)
  252. return merge(bquerymax(l,mid,lc(now),L,R),bquerymax(mid+1,r,rc(now),L,R));
  253. if(L<=mid)
  254. return bquerymax(l,mid,lc(now),L,R);
  255. return bquerymax(mid+1,r,rc(now),L,R);
  256. }
  257. int main(){
  258. scanf("%d%d",&n,&m);
  259. for(int i=1;i<=n;i++)
  260. scanf("%d",&a[i]);
  261. abuild(1,n,1);
  262. for(int i=1;i<n;i++)
  263. b[i]=a[i]^a[i+1];
  264. bbuild(1,n,1);
  265. for(int i=1;i<=m;i++){
  266. scanf("%d%d%d",&qo[i],&ql[i],&qr[i]);
  267. if(qo[i]==3)
  268. scanf("%d",&qk[i]);
  269. }
  270. for(int i=1;i<=m;i++){
  271. int opt=qo[i],l=ql[i],r=qr[i],k=qk[i];
  272. if(opt==0){
  273. if(l>1){
  274. int x=aquery(1,n,1,l-1);
  275. if(bget(1,n,1,l-1)!=x)
  276. bmodify(1,n,1,l-1,x);
  277. }
  278. if(r<n){
  279. int y=aquery(1,n,1,r+1);
  280. if(bget(1,n,1,r)!=y)
  281. bmodify(1,n,1,r,y);
  282. }
  283. if(l<r)
  284. bupdate(1,n,1,l,r-1),cupdate(1,n,1,l,r-1);
  285. aupdate(1,n,1,l,r,0);
  286. }
  287. if(opt==1){
  288. if(l>1){
  289. int x=aquery(1,n,1,l-1)^1;
  290. if(bget(1,n,1,l-1)!=x)
  291. bmodify(1,n,1,l-1,x);
  292. }
  293. if(r<n){
  294. int y=aquery(1,n,1,r+1)^1;
  295. if(bget(1,n,1,r)!=y)
  296. bmodify(1,n,1,r,y);
  297. }
  298. if(l<r)
  299. bupdate(1,n,1,l,r-1),cupdate(1,n,1,l,r-1);
  300. aupdate(1,n,1,l,r,1);
  301. }
  302. if(opt==2){
  303. int x=bget(1,n,1,l-1),y=bget(1,n,1,r);
  304. if(l>1)
  305. bmodify(1,n,1,l-1,bget(1,n,1,l-1)^1);
  306. if(r<n)
  307. bmodify(1,n,1,r,bget(1,n,1,r)^1);
  308. aupdatexor(1,n,1,l,r);
  309. }
  310. if(opt==3){
  311. if(l==r)
  312. puts("0");
  313. else lst=section{-1,-1},printf("%d\n",bquerysum(1,n,1,l,r-1,k-1));
  314. }
  315. if(opt==4){
  316. if(l==r)
  317. puts("1");
  318. else printf("%d\n",bquerymax(1,n,1,l,r-1).maxx+1);
  319. }
  320. }
  321. return 0;
  322. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注