线段树分裂合并

实现了线段树的分裂合并。题意大概是在长度2^30的序列中实现区间提取,区间合并。

复杂度nlogn,我也不知道为什么。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define inf 0x3f3f3f3f
  6 #define ls a[x].l,l,mid
  7 #define rs a[x].r,mid+1,r
  8 #define N 10000000
  9 using namespace std;
 10 struct node
 11 {
 12     int l,r,sum,lazy;
 13 }a[N];
 14 int cnt;int now;
 15 int n;
 16 const int sz=1<<30;
 17 int root[200005];int rt;
 18 void push_down(int x,int l,int mid,int r)
 19 {
 20     if(a[x].lazy)
 21     {
 22         a[x].l=++cnt;
 23         a[x].r=++cnt;
 24         a[a[x].l].lazy=1;a[a[x].r].lazy=1;
 25         a[a[x].l].sum=(mid-l+1);a[a[x].r].sum=(r-mid);
 26         a[x].lazy=0;
 27     }
 28     return ;
 29 }
 30 void spilt(int x,int l,int r,int k,int y)
 31 {
 32     int mid=(l+r)>>1;
 33     push_down(x,l,mid,r);
 34     if(a[a[x].l].sum<=k)
 35     {
 36         a[y].l=a[x].l;
 37         k-=a[a[x].l].sum;
 38         a[x].l=0;
 39         if(k)a[y].r=++cnt,spilt(a[x].r,mid+1,r,k,a[y].r);
 40     }
 41     else a[y].l=++cnt,spilt(a[x].l,l,mid,k,a[y].l);
 42     a[x].sum=a[a[x].l].sum+a[a[x].r].sum;
 43     a[y].sum=a[a[y].l].sum+a[a[y].r].sum;
 44 }
 45 void merge(int x,int y,int l,int r)
 46 {
 47     if(l==r)
 48     {
 49         a[x].sum=1;
 50         return ;
 51     }
 52     int mid=(l+r)>>1;
 53     push_down(x,l,mid,r);push_down(y,l,mid,r);
 54     if(a[y].l)
 55     {
 56         if(!a[x].l)a[x].l=a[y].l;
 57         else merge(a[x].l,a[y].l,l,mid);
 58     }
 59     if(a[y].r)
 60     {
 61         if(!a[x].r)a[x].r=a[y].r;
 62         else merge(a[x].r,a[y].r,mid+1,r);
 63     }
 64     a[x].sum=a[a[x].l].sum+a[a[x].r].sum;
 65     return ;
 66 }
 67 int find(int x,int l,int r,int k)
 68 {
 69     if(l==r)return l;
 70     int mid=(l+r)>>1;
 71     push_down(x,l,mid,r);
 72     if(a[a[x].l].sum>=k)return find(a[x].l,l,mid,k);
 73     else find(a[x].r,mid+1,r,k-a[a[x].l].sum);
 74 }
 75 int main()
 76 {
 77     int cas;
 78     scanf("%d",&cas);
 79     while(cas--)
 80     {
 81         scanf("%d",&n);
 82         for(int i=1;i<=cnt;i++)
 83         {
 84             a[i].l=a[i].r=a[i].sum=0;a[i].lazy=0;
 85         }
 86         cnt=1;now=0;rt=1;
 87         a[1].lazy=1;a[1].sum=sz;
 88         int t1,t2,t3;
 89         for(int i=1;i<=n;i++)
 90         {
 91             scanf("%d",&t1);
 92             if(t1==1)
 93             {
 94                 now++;
 95                 scanf("%d",&t2);
 96                 if(a[rt].sum<t2)
 97                 {
 98                     puts("failed");
 99                     continue;
100                 }
101                 if(a[rt].sum==t2)
102                 {
103                     root[now]=rt;
104                     rt=0;
105                 }
106                 else 
107                 {
108                     root[now]=++cnt;
109                     spilt(rt,0,sz-1,t2,root[now]);
110                 }
111                 puts("ok");
112             }
113             else if(t1==2)
114             {
115                 scanf("%d",&t2);
116                 if(!root[t2])
117                 {
118                     puts("failed");
119                     continue;
120                 }
121                 else if(!rt) rt=root[t2];
122                 else merge(rt,root[t2],0,sz-1);
123                 puts("ok");root[t2]=0;
124             }
125             else
126             {
127                 scanf("%d%d",&t2,&t3);t3++;
128                 if(a[root[t2]].sum<t3)puts("failed");
129                 else
130                 {
131                     printf("%d\n",find(root[t2],0,sz-1,t3));
132                 }
133                 
134             }
135         }
136     }
137     return 0;
138 }

 

posted @ 2017-02-12 09:50  SD_le  阅读(842)  评论(0编辑  收藏  举报
重置按钮