码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3196 树套树模板

时间:2016-12-08 21:25:31      阅读:312      评论:0      收藏:0      [点我收藏+]

标签:line   can   pac   min   class   str   二分   scan   inf   

    然而我还是在继续刷水题。。。

    终于解开了区间第k大的心结。。。

    比较裸的线段树套平衡树,比较不好想的是求区间第k大时需要二分一下答案,然后问题就转化为了第一个操作。复杂度nlog3n。跑的比较慢。。。

    在查前驱后继的时候写错了。。。如果要直接赋值ans的话前驱是k[x]<=z,后继是k[x]<z,如果都写<的话需要取max和min。。。(不是第一次犯这种错了)

   

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lc x*2,l,mid
  6 #define rc x*2+1,mid+1,r
  7 #define ls(x) ch[x][0]
  8 #define rs(x) ch[x][1]
  9 #define inf 0x3f3f3f3f
 10 using namespace std;
 11 int n,m;
 12 int root[50005*50];
 13 int size[50005*50],k[50005*50];
 14 int ch[50005*50][2],fa[50005*50];
 15 int a[50005];
 16 int cnt;
 17 inline void push_up(int x)
 18 {
 19     size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
 20     return ;
 21 }
 22 inline void rotate(int p)
 23 {
 24     int q=fa[p],y=fa[q],x=(ch[q][1]==p);
 25     ch[q][x]=ch[p][x^1];fa[ch[q][x]]=q;
 26     ch[p][x^1]=q;fa[q]=p;fa[p]=y;
 27     if(y)
 28     {
 29         if(ls(y)==q)ch[y][0]=p;
 30         else ch[y][1]=p;
 31     }
 32     push_up(q);push_up(p);
 33 }
 34 inline void splay(int now,int x)
 35 {
 36     for(int y;y=fa[x];rotate(x))
 37     {
 38         if(fa[y])
 39         {
 40             if((ls(y)==x&&ls(fa[y])==y)||(rs(y)==x&&rs(fa[y])==y))rotate(y);
 41             else rotate(x);
 42         }
 43     }
 44     root[now]=x;
 45 }
 46 inline void insert(int now,int x,int z)
 47 {
 48     size[x]++;
 49     while(ch[x][k[x]<z])x=ch[x][k[x]<z],size[x]++;
 50     ch[x][k[x]<z]=++cnt;fa[cnt]=x;size[cnt]=1;k[cnt]=z;splay(now,cnt);
 51 }
 52 inline void build(int x,int l,int r)
 53 {
 54     root[x]=++cnt;k[cnt]=a[l];size[cnt]=1;
 55     for(int i=l+1;i<=r;i++)insert(x,root[x],a[i]);
 56     int mid=(l+r)>>1;
 57     if(l<r)build(lc),build(rc);
 58     return ; 
 59 }
 60 inline int fd(int x,int z)
 61 {
 62    int ans=0;
 63    while(x)    
 64    {
 65          if(k[x]>z)
 66          {
 67               x=ch[x][0];
 68       }
 69       else ans+=size[ch[x][0]]+1,x=ch[x][1];
 70    }
 71    return ans;
 72 }
 73 inline int qur(int x,int l,int r,int ll,int rr,int kk)
 74 {
 75     if(ll<=l&&rr>=r)
 76     {
 77         return fd(root[x],kk);
 78     }
 79     int mid=(l+r)>>1;
 80     int ans=0;
 81     if(ll<=mid)ans+=qur(lc,ll,rr,kk);
 82     if(rr>mid)ans+=qur(rc,ll,rr,kk);
 83     return ans;
 84 }
 85 inline int find(int x,int z)
 86 {
 87     if(k[x]==z)return x;
 88     while(ch[x][k[x]<z])
 89     {
 90         x=ch[x][k[x]<z];if(k[x]==z)return x;
 91     }
 92     return 0;
 93 }
 94 inline void del(int now,int x)
 95 {
 96     splay(now,x);
 97     if(!ch[x][0])root[now]=ch[x][1],fa[ch[x][1]]=0;
 98     else if(!ch[x][1])root[now]=ch[x][0],fa[ch[x][0]]=0;
 99     else 
100     {
101         fa[ch[x][0]]=0;int tmp=ch[x][0];
102         while(ch[tmp][1])tmp=ch[tmp][1];
103         splay(now,tmp);ch[tmp][1]=ch[x][1];fa[ch[x][1]]=tmp;push_up(tmp);
104     }
105 }
106 inline void gai(int x,int l,int r,int pos,int z)
107 {
108     insert(x,root[x],z);
109     int x1=find(root[x],a[pos]);
110     del(x,x1);
111     if(l==r)return ;
112     int mid=(l+r)>>1;
113     if(pos<=mid)gai(lc,pos,z);
114     else gai(rc,pos,z);
115 }
116 inline int pre(int x,int z)
117 {
118     int ans=-inf;
119     while(ch[x][k[x]<=z])
120     {
121         if(k[x]<=z)ans=k[x];
122         x=ch[x][k[x]<=z];
123     }if(k[x]<=z)ans=max(ans,k[x]);
124     return ans;
125 }
126 inline int suc(int x,int z)
127 {
128     int ans=inf;
129     while(ch[x][k[x]<z])
130     {
131         if(k[x]>=z)ans=k[x];
132         x=ch[x][k[x]<z];
133     }if(k[x]>=z)ans=min(ans,k[x]);
134     return ans;
135 }
136 inline int qur_pre(int x,int l,int r,int ll,int rr,int kk)
137 {
138     if(l>=ll&&r<=rr)
139     {
140         return pre(root[x],kk);
141     }
142     int ans=-inf;
143     int mid=(l+r)>>1;
144     if(ll<=mid)ans=max(ans,qur_pre(lc,ll,rr,kk));
145     if(rr>mid)ans=max(ans,qur_pre(rc,ll,rr,kk));
146     return ans;
147 }
148 inline int qur_suc(int x,int l,int r,int ll,int rr,int kk)
149 {
150     if(l>=ll&&r<=rr)
151     {
152         return suc(root[x],kk);
153     }
154     int ans=inf;
155     int mid=(l+r)>>1;
156     if(ll<=mid)ans=min(ans,qur_suc(lc,ll,rr,kk));
157     if(rr>mid)ans=min(ans,qur_suc(rc,ll,rr,kk));
158     return ans;
159 }
160 int mn,mx;
161 int main()
162 {
163     scanf("%d%d",&n,&m);mn=inf;mx=-inf;
164     for(int i=1;i<=n;i++)
165     {
166         scanf("%d",&a[i]);mn=min(mn,a[i]);mx=max(mx,a[i]);
167     }
168     build(1,1,n);
169     for(int i=1;i<=m;i++)
170     {
171         int t1;
172         scanf("%d",&t1);
173         int l,r,kk;
174         if(t1==1)
175         { 
176            scanf("%d%d%d",&l,&r,&kk);
177            printf("%d\n",qur(1,1,n,l,r,kk-1)+1);
178         }
179         else if(t1==2)
180         {
181             scanf("%d%d%d",&l,&r,&kk);
182             int ha=mn;int ta=mx;
183             while(ha<=ta)
184             {
185                 int mid=(ha+ta)>>1;
186                 if(qur(1,1,n,l,r,mid)<kk)ha=mid+1;
187                 else ta=mid-1;
188             }
189             printf("%d\n",ha);
190         }
191         else if(t1==3)
192         {
193             scanf("%d%d",&l,&kk);
194             gai(1,1,n,l,kk);a[l]=kk;
195         }
196         else if(t1==4)
197         {
198             scanf("%d%d%d",&l,&r,&kk);
199             printf("%d\n",qur_pre(1,1,n,l,r,kk-1));
200         }
201         else 
202         {
203             scanf("%d%d%d",&l,&r,&kk);
204             printf("%d\n",qur_suc(1,1,n,l,r,kk+1));
205         }
206     }
207     return 0;
208 }

 

bzoj 3196 树套树模板

标签:line   can   pac   min   class   str   二分   scan   inf   

原文地址:http://www.cnblogs.com/ezyzy/p/6146122.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!