CODEVS 4655 序列终结者-splay(区间更新、区间翻转、区间最值)

4655 序列终结者

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 

 

 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。

输入描述 Input Description

第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。

输出描述 Output Description

对于每个第3种操作,给出正确的回答。

样例输入 Sample Input

4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

N<=50000,M<=100000。

 

 

题意中文。

直接以前的题目改一下就可以。

翻转不需要pushup,因为建树的时候已经算过了,再算一次就不对了。更新也不需要pushup,因为加值不影响size。

没脑子的我简直想暴打自己一顿,调了快1个小时bug,怎么也过不了,最后发现是查询3操作,query(l,r),写成query(1,n),简直要死。

mdzz,浪费了一个小时。

 

代码:

  1 //splay
  2 #include<bits/stdc++.h>
  3 using namespace std;
  4 typedef long long ll;
  5 const int maxn=1e5+10;
  6 const int inf=0x3f3f3f3f;
  7 
  8 int root;
  9 int tree[maxn][2],fa[maxn],id[maxn];
 10 int sz[maxn],val[maxn],Max[maxn];
 11 int add[maxn],rev[maxn];
 12 
 13 void pushup(int x)
 14 {
 15     int l=tree[x][0],r=tree[x][1];
 16     Max[x]=max(max(Max[l],Max[r]),val[x]);
 17     sz[x]=sz[l]+sz[r]+1;
 18 }
 19 
 20 void pushdown(int x)
 21 {
 22     int l=tree[x][0],r=tree[x][1];
 23     if(add[x]){
 24         if(l) val[l]+=add[x],Max[l]+=add[x],add[l]+=add[x];
 25         if(r) val[r]+=add[x],Max[r]+=add[x],add[r]+=add[x];
 26         add[x]=0;
 27     }
 28     if(rev[x]){
 29         rev[x]=0;rev[l]^=1;rev[r]^=1;
 30         swap(tree[x][0],tree[x][1]);
 31     }
 32 }
 33 
 34 void rotate(int x,int &k)
 35 {
 36     int y=fa[x],z=fa[y],l=(tree[y][1]==x),r=l^1;
 37     if(y==k) k=x;
 38     else tree[z][tree[z][1]==y]=x;
 39     fa[tree[x][r]]=y;fa[y]=x;fa[x]=z;
 40     tree[y][l]=tree[x][r];tree[x][r]=y;
 41     pushup(y);pushup(x);
 42 }
 43 
 44 void splay(int x,int &k)
 45 {
 46     while(x!=k){
 47         int y=fa[x],z=fa[y];
 48         if(y!=k){
 49             if((tree[z][0]==y)^(tree[y][0]==x)) rotate(x,k);
 50             else rotate(y,k);
 51         }
 52         rotate(x,k);
 53     }
 54 }
 55 
 56 int find(int x,int rk)
 57 {
 58     if(add[x]||rev[x]) pushdown(x);
 59     int l=tree[x][0],r=tree[x][1];
 60     if(sz[l]+1==rk) return x;
 61     else if(sz[l]>=rk) return find(l,rk);
 62     else return find(r,rk-sz[l]-1);
 63 }
 64 
 65 int split(int l,int r)
 66 {
 67     int x=find(root,l),y=find(root,r+2);
 68     splay(x,root);splay(y,tree[x][1]);
 69     return tree[y][0];
 70 }
 71 
 72 void rever(int l,int r)
 73 {
 74     int x=split(l,r),y=fa[x];
 75     rev[x]^=1;
 76 //    swap(tree[x][0],tree[x][1]);
 77 //    pushup(y);pushup(fa[y]);
 78 }
 79 
 80 void update(int l,int r,int v)
 81 {
 82     int x=split(l,r),y=fa[x];
 83     val[x]+=v;Max[x]+=v;add[x]+=v;
 84 //    pushup(y);pushup(fa[y]);
 85 }
 86 
 87 int find_max(int l,int r)
 88 {
 89     int x=split(l,r);
 90     return Max[x];
 91 }
 92 
 93 void build(int l,int r,int f)
 94 {
 95     if(l>r) return ;
 96     if(l==r){
 97         fa[l]=f;
 98         sz[l]=1;
 99         val[l]=0;
100         tree[f][l>=f]=l;
101         return ;
102     }
103 
104     int m=(l+r)>>1;
105     build(l,m-1,m);
106     build(m+1,r,m);
107     fa[m]=f;
108     pushup(m);
109     tree[f][m>=f]=m;
110 }
111 
112 int main()
113 {
114     int n,m;
115     scanf("%d%d",&n,&m);
116 //    for(int i=1;i<=n+2;i++){
117 //        id[i]=i;
118 //    }
119     Max[0]=-inf;
120     build(1,n+2,0);
121     root=(n+3)>>1;
122     for(int i=1;i<=m;i++){
123         int op;
124         scanf("%d",&op);
125         if(op==1){
126             int l,r,v;
127             scanf("%d%d%d",&l,&r,&v);
128             update(l,r,v);
129         }
130         else if(op==2){
131             int l,r;
132             scanf("%d%d",&l,&r);
133             rever(l,r);
134         }
135         else if(op==3){
136             int l,r;
137             scanf("%d%d",&l,&r);
138             int maxx=find_max(l,r);
139             printf("%d\n",maxx);
140         }
141     }
142     return 0;
143 }

 

 

 

滚了。

 

posted @ 2019-04-21 21:35  ZERO-  阅读(370)  评论(0编辑  收藏  举报