[BZOJ1251]序列终结者

题目大意:
  维护一个长度为$n(n\leq50000)$的序列,支持区间加、区间反转、区间最值。操作共$m(m\leq100000)$次。

思路:
  Splay维护区间,注意操作完如果对上面的结点有贡献,就一定要把这个点转到上面。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<climits>
  4 #include<algorithm>
  5 inline int getint() {
  6     register char ch;
  7     register bool neg=false;
  8     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
  9     register int x=ch^'0';
 10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 11     return neg?-x:x;
 12 }
 13 const int N=50003;
 14 class SplayTree {
 15     private:
 16         int val[N],par[N],size[N],ch[N][2],max[N],tag[N],root;
 17         bool rev[N];
 18         void push_up(const int &p) {
 19             size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
 20             max[p]=std::max(val[p],std::max(max[ch[p][0]],max[ch[p][1]]));
 21         }
 22         void push_down(const int &p) {
 23             if(rev[p]) {
 24                 std::swap(ch[p][0],ch[p][1]);
 25                 rev[ch[p][0]]^=1;
 26                 rev[ch[p][1]]^=1;
 27                 rev[p]=0;
 28             }
 29             if(ch[p][0]) {
 30                 tag[ch[p][0]]+=tag[p];
 31                 val[ch[p][0]]+=tag[p];
 32                 max[ch[p][0]]+=tag[p];
 33             }
 34             if(ch[p][1]) {
 35                 tag[ch[p][1]]+=tag[p];
 36                 val[ch[p][1]]+=tag[p];
 37                 max[ch[p][1]]+=tag[p];
 38             }
 39             tag[p]=0;
 40         }
 41         void rotate(const int &x) {
 42             const int y=par[x],z=par[y];
 43             push_down(y),push_down(x);
 44             const int b=x==ch[y][0];
 45             ch[par[par[ch[y][!b]=ch[x][b]]=y]=x][b]=y;
 46             par[ch[z][y==ch[z][1]]=x]=z;
 47             push_up(y),push_up(x);
 48         }
 49         void splay(int x,const int &goal) {
 50             for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) {
 51                 if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y);
 52             }
 53             if(!goal) root=x;
 54         }
 55         int find(int x) {
 56             for(register int y=root;;y=ch[y][size[ch[y][0]]<x]) {
 57                 push_down(y);
 58                 if(par[y]&&y==ch[par[y]][1]) x-=size[ch[par[y]][0]]+1;
 59                 if(size[ch[y][0]]==x) return y;
 60             }
 61         }
 62     public:
 63         void build(const int &n) {
 64             max[0]=INT_MIN;
 65             for(register int i=1;i<=n+2;i++) par[ch[i-1][1]=i]=i-1;
 66             size[n+2]=1;
 67             splay(n+2,0);
 68         }
 69         void modify(const int &l,const int &r,const int &x) {
 70             splay(find(l-1),0);
 71             splay(find(r+1),root);
 72             if(!ch[ch[root][1]][0]) return;
 73             tag[ch[ch[root][1]][0]]=x;
 74             val[ch[ch[root][1]][0]]+=x;
 75             max[ch[ch[root][1]][0]]+=x;
 76             splay(ch[ch[root][1]][0],0);
 77         }
 78         void reverse(const int &l,const int &r) {
 79             splay(find(l-1),0);
 80             splay(find(r+1),root);
 81             if(!ch[ch[root][1]][0]) return;
 82             rev[ch[ch[root][1]][0]]^=1;
 83         }
 84         int query(const int &l,const int &r) {
 85             splay(find(l-1),0);
 86             splay(find(r+1),root);
 87             return max[ch[ch[root][1]][0]];
 88         }
 89 };
 90 SplayTree t;
 91 int main() {
 92     t.build(getint());
 93     for(register int i=getint();i;i--) {
 94         const int opt=getint(),l=getint(),r=getint();
 95         if(opt==1) t.modify(l,r,getint());
 96         if(opt==2) t.reverse(l,r);
 97         if(opt==3) printf("%d\n",t.query(l,r));
 98     }
 99     return 0;
100 }

 

posted @ 2018-03-06 15:21  skylee03  阅读(92)  评论(0编辑  收藏  举报