splay模板

模板是从http://blog.csdn.net/crazy_ac/article/details/8034190这位大爷博客里找到的。。。但是在由于是功能挺全的一个版本,在一些题里可能维护了一些不必要的值(可能自己在操作步骤写丑了= =)而导致超时。。所以使用的时候还是要注意一下。。

上模板。。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 const int inf  = ~0u>>2;
  4 #define L ch[x][0]
  5 #define R ch[x][1]
  6 #define KT (ch[ ch[rt][1] ][0])
  7 const int maxn = 500010;
  8 int lim;
  9 struct SplayTree {
 10     int sz[maxn];
 11     int ch[maxn][2];
 12     int pre[maxn];
 13     int rt,top;
 14     inline void up(int x){
 15         sz[x]  = cnt[x]  + sz[ L ] + sz[ R ];
 16     }
 17     inline void Rotate(int x,int f){
 18         int y=pre[x];
 19         ch[y][!f] = ch[x][f];
 20         pre[ ch[x][f] ] = y;
 21         pre[x] = pre[y];
 22         if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
 23         ch[x][f] = y;
 24         pre[y] = x;
 25         up(y);
 26     }
 27     inline void Splay(int x,int goal){//将x旋转到goal的下面
 28         while(pre[x] != goal){
 29             if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);
 30             else   {
 31                 int y=pre[x],z=pre[y];
 32                 int f = (ch[z][0]==y);
 33                 if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
 34                 else Rotate(y,f),Rotate(x,f);
 35             }
 36         }
 37         up(x);
 38         if(goal==0) rt=x;
 39     }
 40     inline void RTO(int k,int goal){//将第k位数旋转到goal的下面
 41         int x=rt;
 42         while(sz[ L ] != k-1) {
 43             if(k < sz[ L ]+1) x=L;
 44             else {
 45                 k-=(sz[ L ]+1);
 46                 x = R;
 47             }
 48         }
 49         Splay(x,goal);
 50     }
 51     inline void vist(int x){
 52         if(x){
 53             printf("结点%2d : 左儿子  %2d   右儿子  %2d   val:%2d sz=%d  cnt:%d\n",x,L,R,val[x],sz[x],cnt[x]);
 54             vist(L);
 55             vist(R);
 56         }
 57     }
 58     void debug() {
 59         puts("");
 60         vist(rt);
 61         puts("");
 62     }
 63     inline void Newnode(int &x,int c,int f){
 64         x=++top;
 65         L = R = 0;
 66         pre[x] = f;
 67         sz[x]=1; cnt[x]=1;
 68         val[x] = c;
 69     }
 70     inline void init(){
 71         ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
 72         rt=top=0; cnt[0]=0;
 73     }
 74     inline void Insert(int &x,int key,int f){
 75         if(!x) {
 76             Newnode(x,key,f);
 77             Splay(x,0);//注意插入完成后splay
 78             return ;
 79         }
 80         if(key==val[x]){
 81             cnt[x]++;
 82             sz[x]++;
 83             Splay(x,0);//注意插入完成后splay
 84             return ;
 85         }else if(key<val[x]) {
 86             Insert(L,key,x);
 87         } else {
 88             Insert(R,key,x);
 89         }
 90         up(x);
 91     }
 92     void Del_root(){//删除根节点
 93         int t=rt;
 94         if(ch[rt][1]) {
 95             rt=ch[rt][1];
 96             RTO(1,0);
 97             ch[rt][0]=ch[t][0];
 98             if(ch[rt][0]) pre[ch[rt][0]]=rt;
 99         }
100         else rt=ch[rt][0];
101         pre[rt]=0;
102         up(rt);
103     }
104     void findpre(int x,int key,int &ans){//找前驱节点
105         if(!x)  return ;
106         if(val[x] <= key){
107             ans=x;
108             findpre(R,key,ans);
109         } else
110             findpre(L,key,ans);
111     }
112     void findsucc(int x,int key,int &ans){//找后继节点
113         if(!x) return ;
114         if(val[x]>=key) {
115             ans=x;
116             findsucc(L,key,ans);
117         } else
118             findsucc(R,key,ans);
119     }
120     inline int find_kth(int x,int k){ //第k小的数
121         if(k<sz[L]+1) {
122             return find_kth(L,k);
123         }else if(k > sz[ L ] + cnt[x] ) 
124             return find_kth(R,k-sz[L]-cnt[x]);
125         else{ 
126             Splay(x,0);
127             return val[x];
128         }
129     }
130     int find(int x,int key){
131         if(!x) return 0;
132         else if(key < val[x])  return find(L,key);
133         else if(key > val[x])  return find(R,key);
134         else return x;
135     }
136     int getmin(int x){
137         while(L) x=L;    return val[x];
138     }
139     int getmax(int x){
140         while(R) x=R;   return val[x];
141     }
142     //确定key的排名
143     int getrank(int x,int key,int cur){//cur:当前已知比要求元素(key)小的数的个数
144         if(key == val[x])  
145             return sz[L] + cur + 1;
146         else if(key < val[x])
147             getrank(L,key,cur);
148         else 
149             getrank(R,key,cur+sz[L]+cnt[rt]);
150     }
151     int get_lt(int x,int key){//小于key的数的个数 lt:less than 
152         if(!x) return 0;
153         if(val[x]>=key) return get_lt(L,key);
154         return cnt[x]+sz[L]+get_lt(R,key);
155     }
156     int get_mt(int x,int key){//大于key的数的个数 mt:more than
157         if(!x) return 0;
158         if(val[x]<=key) return get_mt(R,key) ;
159         return cnt[x]+sz[R]+get_mt(L,key);
160     }
161     void del(int &x,int f){//删除小于lim的所有的数所在的节点
162         if(!x) return ;
163         if(val[x]>=lim){
164             del(L,x);
165         } else {
166             x=R; 
167             pre[x]=f;
168             if(f==0)  rt=x;
169             del(x,f);
170         }
171         if(x)  up(x);
172     }
173     inline void update(){
174         del(rt,0);
175     }
176     int get_mt(int key) {
177         return get_mt(rt,key);
178     }
179     int get_lt(int key) {
180         return get_lt(rt,key);
181     }
182     void insert(int key) {
183         Insert(rt,key,0);
184     }
185     void Delete(int key) {
186         int node=find(rt,key);
187         Splay(node,0);
188         cnt[rt]--;
189         if(!cnt[rt])Del_root();
190     }
191     int kth(int k) {
192         return find_kth(rt,k);
193     }
194     int cnt[maxn];
195     int val[maxn];
196     int lim;
197 }spt;
View Code

 建树时候的函数

 1 void built(int &x,int l,int r,int father)
 2     {
 3         if(l>r)
 4         return ;
 5         int mid=(l+r)/2;
 6         Newnode(x,a[mid],father);
 7         if(l<mid)
 8         built(ch[x][0],l,mid-1,x);
 9         if(r>mid)
10         built(ch[x][1],mid+1,r,x);
11         up(x);
12     }
View Code

 

 

然后是自己在poj3468中参照cxlove大爷改的lazy版本。。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 const int inf  = ~0u>>2;
  4 #define L ch[x][0]
  5 #define R ch[x][1]
  6 #define KT (ch[ ch[rt][1] ][0])
  7 #define ll long long
  8 const int maxn = 100010;
  9 int lim;
 10 int a[maxn],n;
 11 ll lazy[maxn],sum[maxn];
 12 using namespace std;
 13 struct SplayTree {
 14     int sz[maxn];
 15     int ch[maxn][2];
 16     int pre[maxn];
 17     int rt,top;
 18     inline void up(ll x){
 19         sz[x]  =sz[ L ] + sz[ R ]+1;
 20         sum[x] = val[x] + sum[L]+sum[R]+lazy[x];
 21     }
 22     inline void pushdown(int x)
 23     {
 24         if(lazy[x])
 25         {
 26             if(L)
 27             {
 28                 lazy[L]+=lazy[x];
 29                 sum[L]+=lazy[x]*sz[L];
 30             }
 31             if(R)
 32             {
 33                 lazy[R]+=lazy[x];
 34                 sum[R]+=lazy[x]*sz[R];
 35             }
 36             val[x]+=lazy[x];
 37             lazy[x]=0;
 38         }
 39     }
 40     inline void Rotate(int x,int f){
 41         int y=pre[x];
 42         pushdown(x);
 43         pushdown(y);
 44         ch[y][!f] = ch[x][f];
 45         pre[ ch[x][f] ] = y;
 46         pre[x] = pre[y];
 47         if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
 48         ch[x][f] = y;
 49         pre[y] = x;
 50         up(y);
 51     }
 52     inline void Splay(int x,int goal){//将x旋转到goal的下面
 53         pushdown(x);
 54         while(pre[x] != goal){
 55             if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);
 56             else   {
 57                 int y=pre[x],z=pre[y];
 58                 int f = (ch[z][0]==y);
 59                 if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
 60                 else Rotate(y,f),Rotate(x,f);
 61             }
 62         }
 63         up(x);
 64         if(goal==0) rt=x;
 65     }
 66     void RTO(int k,int goal) {
 67     int r=rt;
 68     pushdown(r);
 69     while(sz[ch[r][0]]!=k){
 70         if(k<sz[ch[r][0]]){
 71             r=ch[r][0];
 72         } else {
 73             k-=(sz[ch[r][0]]+1);
 74             r=ch[r][1];
 75         }
 76         pushdown(r);
 77     }
 78     Splay(r,goal);
 79 }
 80     inline void Newnode(int &x,int c,int f){
 81         x=++top;
 82         L = R = 0;
 83         pre[x] = f;
 84         sz[x]=1;
 85         lazy[x]=0;
 86         val[x] = c;
 87         sum[x]=c;
 88     }
 89     inline void init(){
 90         ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
 91         rt=top=0;
 92         Newnode(rt,-1,0);
 93         Newnode(ch[rt][1],-1,rt);
 94         sz[rt]=2;
 95         built(KT,1,n,ch[rt][1]);
 96         up(ch[rt][1]);
 97         up(rt);
 98     }
 99     /*void BulidTree(int &x,int l,int r,int father){
100     if(l>r)
101         return;
102     int mid=(l+r)/2;
103     Newnode(x,a[mid],father);
104     if(l<mid)
105         BulidTree(ch[x][0],l,mid-1,x);
106     if(r>mid)
107         BulidTree(ch[x][1],mid+1,r,x);
108     up(x);
109     }*/
110     void built(int &x,int l,int r,int father)
111     {
112         if(l>r)
113         return ;
114         int mid=(l+r)/2;
115         Newnode(x,a[mid],father);
116         if(l<mid)
117         built(ch[x][0],l,mid-1,x);
118         if(r>mid)
119         built(ch[x][1],mid+1,r,x);
120         up(x);
121     }
122     void Update()
123     {
124         int l,r,c;
125         scanf("%d%d%d",&l,&r,&c);
126         RTO(l-1,0);
127         RTO(r+1,rt);
128         lazy[KT]+=c;
129         sum[KT]+=c*sz[KT];
130      } 
131     void ask()
132     {
133         int l,r;
134         scanf("%d%d",&l,&r);
135         RTO(l-1,0);
136         RTO(r+1,rt);
137         printf("%lld\n",sum[KT]);
138     }
139     int val[maxn];
140 }spt;
141 int main()
142 {
143     int m;
144     scanf("%d%d",&n,&m);
145     for(ll i=1;i<=n;i++)
146     scanf("%d",&a[i]);
147     spt.init();
148     for(ll i=1;i<=m;i++)
149     {
150         char x;
151         scanf(" %c",&x);
152         if(x=='Q')
153         spt.ask();
154         else
155         spt.Update();
156     }
157     return 0;
158  } 
View Code

对于建树时使用的类似线段树的写法让我又对splay了解了许多。。。

posted @ 2016-10-03 14:42  啊啊啊啊啊啊啊啊啊阿  阅读(223)  评论(0编辑  收藏  举报