bzoj 1251序列终结者 splay 区间翻转,最值,区间更新
序列终结者
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 4594 Solved: 1939
[Submit][Status][Discuss]
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
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。
Output
对于每个第3种操作,给出正确的回答。
Sample Input
4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【数据范围】
N<=50000,M<=100000。
【数据范围】
N<=50000,M<=100000。
题解:
splay的一些操作都在了,区间翻转,区间求最值,区间加一个数。
区间翻转需要注意一些,最值也是,写写就熟了。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define inf 1000000007 8 #define N 50007 9 #define ls c[p][0] 10 #define rs c[p][1] 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();} 16 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 20 int n,m,rt; 21 int fa[N],val[N],rev[N],mx[N],sz[N],flag[N],c[N][2]; 22 23 inline void update(int p) 24 { 25 sz[p]=sz[ls]+sz[rs]+1; 26 mx[p]=max(mx[ls],mx[rs]); 27 mx[p]=max(mx[p],val[p]); 28 } 29 inline void pushdown(int p) 30 { 31 if (flag[p]) 32 { 33 int f=flag[p];flag[p]=0; 34 if (ls){flag[ls]+=f,mx[ls]+=f,val[ls]+=f;} 35 if (rs){flag[rs]+=f,mx[rs]+=f,val[rs]+=f;} 36 } 37 if (rev[p]) 38 { 39 rev[p]^=1; 40 rev[ls]^=1,rev[rs]^=1; 41 swap(c[p][1],c[p][0]); 42 } 43 } 44 void rotate(int x,int &k) 45 { 46 int y=fa[x],z=fa[y],l,r; 47 if (c[y][0]==x) l=0;else l=1;r=l^1; 48 if (y==k) k=x;//交换后x就等于y 49 else if (c[z][0]==y) c[z][0]=x; 50 else c[z][1]=x; 51 fa[x]=z,fa[y]=x,fa[c[x][r]]=y; 52 c[y][l]=c[x][r],c[x][r]=y; 53 update(y),update(x); 54 } 55 void splay(int x,int &k) 56 { 57 while(x!=k) 58 { 59 int y=fa[x],z=fa[y]; 60 if (y!=k) 61 { 62 if (c[y][0]==x^c[z][0]==y) rotate(x,k); 63 else rotate(y,k); 64 } 65 rotate(x,k); 66 } 67 } 68 int find(int p,int num) 69 { 70 pushdown(p); 71 if (sz[ls]>=num) return find(ls,num); 72 else if (sz[ls]+1==num) return p; 73 else return find(rs,num-sz[ls]-1); 74 } 75 void add(int l,int r,int z) 76 { 77 int x=find(rt,l),y=find(rt,r+2); 78 splay(x,rt),splay(y,c[x][1]); 79 int now=c[c[x][1]][0]; 80 val[now]+=z,flag[now]+=z,mx[now]+=z; 81 } 82 void spin(int l,int r) 83 { 84 int x=find(rt,l),y=find(rt,r+2); 85 splay(x,rt),splay(y,c[x][1]); 86 int now=c[c[x][1]][0]; 87 rev[now]^=1; 88 } 89 int query(int l,int r) 90 { 91 int x=find(rt,l),y=find(rt,r+2); 92 splay(x,rt),splay(y,c[x][1]); 93 int now=c[c[x][1]][0]; 94 return mx[now]; 95 } 96 void build(int l,int r,int p) 97 { 98 if (l>r) return; 99 if (l==r) 100 { 101 fa[l]=p,sz[l]=1; 102 if (l<p) c[p][0]=l; 103 else c[p][1]=l; 104 return; 105 } 106 int mid=(l+r)>>1; 107 build(l,mid-1,mid),build(mid+1,r,mid); 108 fa[mid]=p; 109 if (mid<p) c[p][0]=mid; 110 else c[p][1]=mid; 111 update(mid); 112 } 113 int main() 114 { 115 freopen("fzy.in","r",stdin); 116 freopen("fzy.out","w",stdout); 117 118 n=read(),m=read();mx[0]=-inf; 119 build(1,n+2,0),rt=(n+3)>>1; 120 while(m--) 121 { 122 int flag=read(),x,y,z; 123 switch(flag) 124 { 125 case 1:x=read(),y=read(),z=read();add(x,y,z);break; 126 case 2:x=read(),y=read();spin(x,y);break; 127 case 3:x=read(),y=read();printf("%d\n",query(x,y));break; 128 } 129 } 130 }