【BZOJ1251】序列终结者 Splay

一道模板题,一直没发现自己的快速读入读不了负数,我竟然能活到现在真是万幸

  1 #include <iostream>
  2 #include <cstdio>
  3 #define inf -0x7fffffff
  4 #define N 50010
  5 using namespace std;
  6 struct SplayNode 
  7 {
  8     SplayNode();
  9     SplayNode *fa,*ch[2];
 10     //SplayNode(int x);
 11     int data,maxn,size,add;
 12     bool rev;
 13     void push();
 14     bool chr() {return this==fa->ch[1];}
 15     void updata()
 16     {
 17         size=ch[0]->size+ch[1]->size+1;
 18         maxn=max(max(ch[0]->maxn,ch[1]->maxn),data);
 19     }
 20     void setc(SplayNode *x,int t) {this->ch[t]=x; x->fa=this;}
 21 }*null;
 22 SplayNode::SplayNode() {fa=ch[1]=ch[0]=null; rev=0;data=add=size=0; maxn=inf;}
 23 void SplayNode::push()
 24     {
 25         if (rev)
 26         {
 27             if (ch[0]!=null) ch[0]->rev^=1;
 28             if (ch[1]!=null) ch[1]->rev^=1;
 29             swap(ch[0],ch[1]);
 30             rev=0;
 31         }
 32         if (add!=0)
 33         {
 34             if (ch[1]!=null) 
 35             {
 36                 ch[1]->add+=add;
 37                 ch[1]->maxn+=add;
 38                 ch[1]->data+=add;
 39             }
 40             if (ch[0]!=null) 
 41             {
 42                 ch[0]->add+=add;
 43                 ch[0]->maxn+=add;
 44                 ch[0]->data+=add;
 45             }
 46             add=0;
 47         }
 48     }
 49 int n,m;
 50 //inline int read() {int ans=0; char c; while ((c=getchar())=='\r' || c=='\n' || c==' '); ans=c-'0'; while (isdigit(c=getchar())) ans=ans*10+c-'0'; return ans;}
 51 namespace Splay
 52 {
 53     SplayNode *Root;
 54     SplayNode pool[N];
 55     int poolnum=0;
 56     SplayNode *NewNode()
 57     {
 58         poolnum++;
 59         pool[poolnum]=SplayNode();
 60         return &pool[poolnum];
 61     }
 62     SplayNode *BuildTree(int l,int r)
 63     {
 64         if (l>r) return null;
 65         SplayNode *re=NewNode();
 66         int mid=(l+r)>>1;
 67         re->data=0;
 68         re->ch[0]=BuildTree(l,mid-1);
 69         re->ch[1]=BuildTree(mid+1,r);
 70         re->ch[0]->fa=re;
 71         re->ch[1]->fa=re;
 72         re->updata();
 73         return re;
 74     }
 75     void rotate(SplayNode *x)
 76     {
 77         SplayNode *r=x->fa;
 78         if (x==null || r==null) return; 
 79         int t=x->chr();
 80         x->push(); r->push();
 81         if (r->fa==null) x->fa=r->fa,Root=x;
 82         else r->fa->setc(x,r->chr());
 83         r->setc(x->ch[t^1],t);
 84         x->setc(r,!t);
 85         r->updata();
 86         x->updata();
 87     }
 88     void splay(SplayNode *x,SplayNode *y)
 89     {
 90         for (;x->fa!=y;rotate(x))
 91             if (x->fa->fa!=y)
 92                 if (x->chr()==x->fa->chr()) rotate(x->fa);
 93                 else rotate(x);
 94     }
 95     SplayNode *Kth(int k)
 96     {
 97         SplayNode *r=Root;
 98         while (r!=null)
 99         {
100             r->push();
101             if (k<=r->ch[0]->size) r=r->ch[0];
102             else if (k==r->ch[0]->size+1) return r;
103             else 
104             {
105                 k-=r->ch[0]->size+1;
106                 r=r->ch[1];
107             }        
108         }
109         return null;
110     }
111     void reverse(int l,int r)
112     {
113         SplayNode *p=Kth(l);
114         SplayNode *s=Kth(r+2);
115         p->push();
116         splay(p,null);
117         s->push();
118         splay(s,p);
119         s->ch[0]->rev^=1;
120     }
121     void Add(int l,int r,int v)
122     {
123         SplayNode *p=Kth(l);
124         SplayNode *s=Kth(r+2);
125         p->push();
126         splay(p,null);
127         s->push();
128         splay(s,p);
129         s->ch[0]->add+=v;
130         s->ch[0]->data+=v;
131         s->ch[0]->maxn+=v;
132     }
133     void query(int l,int r)
134     {
135         SplayNode *p=Kth(l);
136         SplayNode *s=Kth(r+2);
137         p->push();
138         splay(p,null);
139         s->push();
140         splay(s,p);
141         printf("%d\n",s->ch[0]->maxn);
142     }
143 }
144 void init() {null=Splay::NewNode(); *null=SplayNode(); Splay::Root=Splay::BuildTree(0,n+1);}
145 int main()
146 {
147     scanf("%d%d",&n,&m);
148     init();
149     //for (int i=1;i<=n;i++) a[i]=read();
150     //Splay::BuildTree(1,n);
151     for (int i=1;i<=m;i++)
152     {
153         int temp,x,y;
154         scanf("%d%d%d",&temp,&x,&y);
155         //temp=read(); x=read(); y=read();
156         if (temp==1)
157         {
158             int v;
159             scanf("%d",&v);
160             Splay::Add(x,y,v);    
161         }
162         if (temp==2) Splay::reverse(x,y);
163         if (temp==3) Splay::query(x,y);
164     }
165     return 0;
166 }
View Code

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。

HINT

 

Source

 

 
posted @ 2016-03-27 14:30  DMoon  阅读(155)  评论(0编辑  收藏  举报