真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作
n<=300000个点,开始是独立的,m<=300000个操作:
方法一:单点修改、查询,区间修改、查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两棵树u,v时,把v放到u树根节点的最后,使其dfs序最后,最后扫一次把每棵树dfs一下搞出这个序列,然后线段树操作即可。
怎么把v放到u的儿子最后???强制一下连边顺序!!根据你写的邻接表,决定过程中的边是要正连还是倒连以达到目标顺序。有点抽象,见代码。
没写。
方法二:真正“棘手的操作”--可并堆!!!
如果是散散的点再连起来,可并堆的期望深度是小小的,可以做标记下传的!!
大体的思路是,每个块一个堆,然后每个堆的根节点的值再搞一个堆,就可以回答所有询问。然后来看看怎么操作:
U:直接合并。
A1:单点加,那就相当于单点查,单点删,单点加。单点删和单点加详见
单点查的话就标记下传就行了。。
A2:块加,打标记。
A3:是来搞笑的吗,记个全局变量。
F1:单点查,同上。
F2,F3:来搞笑的。
总之,重点在于:两个堆同时操作。
这次复合数据结构题的整体构思比以前有进步,但!!可并堆和并查集的结合非常混乱,这题要再写。
1 #include<string.h> 2 #include<stdlib.h> 3 #include<stdio.h> 4 #include<math.h> 5 //#include<assert.h> 6 #include<algorithm> 7 //#include<iostream> 8 using namespace std; 9 10 int n,m; 11 #define maxn 300011 12 struct leftist 13 { 14 struct Node 15 { 16 int fa,ls,rs,v,dis,add; 17 }a[maxn]; 18 leftist() {a[0].dis=-1;} 19 void addsingle(int x,int v) 20 { 21 if (!x) return; 22 (a[x].v+=v); 23 a[x].add+=v; 24 } 25 void down(int x) 26 { 27 int &p=a[x].ls,&q=a[x].rs; 28 if (a[x].add) {addsingle(p,a[x].add); addsingle(q,a[x].add); a[x].add=0;} 29 } 30 int sta[maxn]; 31 void download(int x) 32 { 33 int top=0; 34 for (int i=x;i;i=a[i].fa) sta[++top]=i; 35 for (;top;top--) down(sta[top]); 36 } 37 int merge(int x,int y) 38 { 39 if (!x || !y) return x^y; 40 if (a[x].v<a[y].v) {int t=x; x=y; y=t;} 41 down(x); 42 a[x].rs=merge(a[x].rs,y); 43 if (a[a[x].ls].dis<a[a[x].rs].dis) {int t=a[x].ls; a[x].ls=a[x].rs; a[x].rs=t;} 44 a[x].dis=a[a[x].rs].dis+1; 45 if (a[x].rs) a[a[x].rs].fa=x; if (a[x].ls) a[a[x].ls].fa=x; 46 return x; 47 } 48 void Delete(int &root,int x) 49 { 50 int y=a[x].fa,w=(x==a[y].rs); x=merge(a[x].ls,a[x].rs); a[x].fa=y; 51 if (!y) {root=x; return;} 52 if (w) a[y].rs=x; else a[y].ls=x; 53 if (a[a[y].ls].dis<a[a[y].rs].dis) {int t=a[y].ls; a[y].ls=a[y].rs; a[y].rs=t;} 54 x=a[y].rs; 55 while (y && a[y].dis!=a[x].dis+1) 56 { 57 a[y].dis=a[x].dis+1; 58 x=y; y=a[y].fa; 59 if (a[a[y].ls].dis<a[a[y].rs].dis) {int t=a[y].ls; a[y].ls=a[y].rs; a[y].rs=t;} 60 x=a[y].rs; 61 } 62 } 63 void push(int id,int &root,int val) 64 { 65 a[id].fa=a[id].ls=a[id].rs=a[id].dis=a[id].add=0; a[id].v=val; 66 root=merge(root,id); 67 } 68 int top(int root) {return a[root].v;} 69 }q,qtot; 70 int root[maxn]; 71 int find(int x) {return x==root[x]?x:(root[x]=find(root[x]));} 72 73 int main() 74 { 75 scanf("%d",&n); 76 for (int i=1,x;i<=n;i++) scanf("%d",&x),q.push(i,root[i],x),qtot.push(i,root[0],x); 77 scanf("%d",&m); 78 char c;int x,y; int totadd=0; 79 for (int i=1;i<=m;i++) 80 { 81 while ((c=getchar())!='U' && c!='A' && c!='F'); 82 if (c=='U') 83 { 84 scanf("%d%d",&x,&y); x=find(x); y=find(y); 85 if (x==y) continue; 86 qtot.Delete(root[0],y); qtot.Delete(root[0],x); 87 root[x]=root[y]=q.merge(x,y); 88 x=root[x]; qtot.push(x,root[0],q.a[x].v); 89 } 90 else if (c=='A') 91 { 92 c=getchar(); 93 if (c=='1') 94 { 95 scanf("%d%d",&x,&y); find(x); 96 qtot.Delete(root[0],root[x]); 97 q.download(x); int tmp=q.a[x].v; 98 q.Delete(root[x],x); int z=root[x]; 99 if (z) root[z]=z,q.push(x,root[z],tmp+y),root[x]=root[z]; 100 else q.push(x,root[x],tmp+y); 101 qtot.push(root[x],root[0],q.a[root[x]].v); 102 } 103 else if (c=='2') 104 { 105 scanf("%d%d",&x,&y); x=find(x); qtot.Delete(root[0],x); 106 q.addsingle(x,y); qtot.push(x,root[0],q.a[x].v); 107 } 108 else if (c=='3') 109 { 110 scanf("%d",&x); 111 totadd+=x; 112 } 113 } 114 else 115 { 116 c=getchar(); 117 if (c=='1') 118 { 119 scanf("%d",&x); 120 q.download(x); 121 printf("%d\n",q.a[x].v+totadd); 122 } 123 else if (c=='2') 124 { 125 scanf("%d",&x); x=find(x); 126 printf("%d\n",q.a[x].v+totadd); 127 } 128 else printf("%d\n",qtot.a[root[0]].v+totadd); 129 } 130 } 131 return 0; 132 }