1. 程式人生 > >真--可並堆模板--BZOJ2333: [SCOI2011]棘手的操作

真--可並堆模板--BZOJ2333: [SCOI2011]棘手的操作

def 操作 aps left getchar() 。。 每次 全局 log

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 }
View Code

真--可並堆模板--BZOJ2333: [SCOI2011]棘手的操作