线段树分裂合并
实现了线段树的分裂合并。题意大概是在长度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 }