bzoj 1251序列终结者 splay 区间翻转,最值,区间更新

序列终结者

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 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

Sample Output

2
【数据范围】
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 }

 

posted @ 2017-12-24 14:13  Kaiser-  阅读(266)  评论(0编辑  收藏  举报