1 条题解
-
0
自动搬运
来自洛谷,原作者为

PurpleWonder
**搬运于
2025-08-24 21:57:01,当前版本为作者最后更新于2018-08-30 14:37:31,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
通过平衡树来维护区间操作的一道比较像模板的题目。
看见楼上的几位大佬用的都是splay,补一发fhq_treap的题解好了。
#include<cstdio> #include<iostream> #define ls(x) t[x].ch[0] #define rs(x) t[x].ch[1] using namespace std; struct node{ int size,key,val,cx,add,tur,ch[2],maxn; }t[100010]; //size:子树大小 key:随机生成的key值 val:当前位置的值 cx:在数组中的位置(好像后面没用到?) add:加法的延迟标记 tur:旋转的延迟标记 ch:左右儿子(用ls(x)与rs(x)表示) maxn:区间的最大值 int n,m,gs,rt; int seed=623; int com,l,r,zhi; inline int rand(){ return seed=(int)((seed*1000000007ll)%0x7fffffff); } //从下向上推时,需要同时更新两个值:最大值与子树大小 inline void push_up(int x){ t[x].size=t[ls(x)].size+t[rs(x)].size+1; t[x].maxn=t[x].val; //防止在最大值为负值时访问到空节点(空节点处最大值为0) if(ls(x))t[x].maxn=max(t[x].maxn,t[ls(x)].maxn); if(rs(x))t[x].maxn=max(t[x].maxn,t[rs(x)].maxn); } //向下推同样需要维护两个值:加的lazy标记与旋转的lazy标记 inline void push_down(int x){ if(t[x].tur){ if(ls(x))t[ls(x)].tur^=1; if(rs(x))t[rs(x)].tur^=1; ls(x)^=rs(x)^=ls(x)^=rs(x); t[x].tur=0; } if(t[x].add){ if(ls(x)){//防止给0节点加上奇奇怪怪的值 t[ls(x)].add+=t[x].add; t[ls(x)].val+=t[x].add; t[ls(x)].maxn+=t[x].add; } if(rs(x)){ t[rs(x)].add+=t[x].add; t[rs(x)].val+=t[x].add; t[rs(x)].maxn+=t[x].add; } t[x].add=0; update(x); } } //正常的分离/合并 int merge(int x,int y){ int now; push_down(x);push_down(y); if(!x || !y)return x|y; if(t[x].key<t[y].key){ now=x,rs(x)=merge(t[x].ch[1],y); } else now=y,ls(y)=merge(x,t[y].ch[0]); push_up(now); return now; } void split(int root,int bz,int &x,int &y){ if(!root){x=y=0;return;} push_down(root); if(t[ls(root)].size>=bz)y=root,split(ls(root),bz,x,ls(y)); else x=root,split(rs(root),bz-t[ls(root)].size-1,rs(x),y); push_up(root); } inline void insert(int x){ t[++gs].key=rand(); t[gs].val=x; t[gs].cx=gs; t[gs].maxn=x; t[gs].size=1; rt=merge(rt,gs); } //对l-r这段区间进行操作时,只需要先把l-r这段区间单独分离出来,再在分出来的区间的根节点上加lazy标记即可 inline void update1(int l,int r,int zhi){ int x,y,z; split(rt,l-1,x,y); split(y,r-l+1,y,z); t[y].maxn+=zhi; t[y].add+=zhi; t[y].val+=zhi; rt=merge(merge(x,y),z); } inline void update2(int l,int r){ int x,y,z; split(rt,l-1,x,y); split(y,r-l+1,y,z); t[y].tur^=1; rt=merge(merge(x,y),z); } inline void query(int l,int r){ int x,y,z; split(rt,l-1,x,y); split(y,r-l+1,y,z); printf("%d\n",t[y].maxn); rt=merge(merge(x,y),z); } int main(){ scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ insert(0); } while(m--){ scanf("%d",&com); if(com==1){scanf("%d %d %d",&l,&r,&zhi),update1(l,r,zhi);} else if(com==2){scanf("%d %d",&l,&r),update2(l,r);} else if(com==3){scanf("%d %d",&l,&r),query(l,r);} } return 0; }
- 1
信息
- ID
- 3102
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者