BZOJ2333:[SCOI2011]棘手的操作(Splay)
Description
有N个节点,标号从1到N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:
U x y: 加一条边,连接第x个节点和第y个节点
A1 x v: 将第x个节点的权值增加v
A2 x v: 将第x个节点所在的连通块的所有节点的权值都增加v
A3 v: 将所有节点的权值都增加v
F1 x: 输出第x个节点当前的权值
F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值
F3: 输出所有节点中,权值最大的节点的权值
Input
输入的第一行是一个整数N,代表节点个数。
接下来一行输入N个整数,a[1], a[2], …, a[N],代表N个节点的初始权值。
再下一行输入一个整数Q,代表接下来的操作数。
最后输入Q行,每行的格式如题目描述所示。
Output
对于操作F1, F2, F3,输出对应的结果,每个结果占一行。
Sample Input
0 0 0
8
A1 3 -20
A1 2 20
U 1 3
A2 1 10
F1 3
F2 3
A3 -10
F3
Sample Output
10
10
HINT
对于30%的数据,保证 N<=100,Q<=10000
对于80%的数据,保证 N<=100000,Q<=100000
对于100%的数据,保证 N<=300000,Q<=300000
对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], …, a[N]<=1000
Solution
第一眼:这不splay启发式合并板子题吗?
然后就开始漫长的写写写调调调
维护多颗splay
U:splay启发式合并,一个个删除小的splay插入到大的splay里面
A1:删除val[x],插入val[x]+v
A2:开个Add数组,维护每颗splay整体加的数
A3:搞个全局变量ALL记一下就好了
F1:直接输出val[x]+Add[x]+ALL
F2:直接输出Max[ID[x]],其中ID是x所属的平衡树编号
F3::这个相当于要维护Max[]的最大值。开个可删堆,每次Max[i]变化的时候就把旧的删掉,新的插入,F3查询的时候直接输出堆顶即可。
emmm话说为什么大部分人都写的堆啊_(Xз」∠)_
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #define N (600000+1000) 5 using namespace std; 6 7 int Son[N][2],Father[N],Size[N]; 8 int ID[N],Add[N],Val[N],Max[N]; 9 int Root[N],n,m,x,y,v,ALL; 10 char opt[10]; 11 priority_queue<int>Heap,Del; 12 13 int Get(int x){return Son[Father[x]][1]==x;} 14 void Update(int x){Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;} 15 void Clear(int x){Son[x][0]=Son[x][1]=Father[x]=Size[x]=Val[x]=0;} 16 17 int Pre(int x) 18 { 19 x=Son[x][0]; 20 while (Son[x][1]) x=Son[x][1]; 21 return x; 22 } 23 24 int Get_Max(int x) 25 { 26 while (Son[x][1]) x=Son[x][1]; 27 return Val[x]; 28 } 29 30 void Rotate(int x) 31 { 32 int wh=Get(x); 33 int fa=Father[x], fafa=Father[fa]; 34 if (fafa) Son[fafa][Son[fafa][1]==fa]=x; 35 Son[fa][wh]=Son[x][wh^1]; Father[fa]=x; 36 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 37 Son[x][wh^1]=fa; Father[x]=fafa; 38 Update(fa); Update(x); 39 } 40 41 void Splay(int x) 42 { 43 for (int fa; (fa=Father[x]); Rotate(x)) 44 if (Father[fa]) 45 Rotate(Get(fa)==Get(x)?fa:x); 46 Root[ID[x]]=x; 47 } 48 49 void Insert(int x,int y,int v) 50 { 51 int now=Root[ID[y]],fa=0; 52 while (1) 53 { 54 fa=now,now=Son[now][v>Val[now]]; 55 if (now==0) 56 { 57 Val[x]=v; Size[x]=1; Father[x]=fa; ID[x]=ID[y]; 58 Son[fa][v>Val[fa]]=x; Splay(x); return; 59 } 60 } 61 } 62 63 void Delete(int x) 64 { 65 Splay(x); 66 if (!Son[Root[ID[x]]][0] && !Son[Root[ID[x]]][1]) 67 { 68 Clear(Root[ID[x]]); 69 Root[ID[x]]=0; 70 return; 71 } 72 if (!Son[Root[ID[x]]][0]) 73 { 74 Root[ID[x]]=Son[Root[ID[x]]][1]; 75 Clear(Father[Root[ID[x]]]); 76 Father[Root[ID[x]]]=0; 77 return; 78 } 79 if (!Son[Root[ID[x]]][1]) 80 { 81 Root[ID[x]]=Son[Root[ID[x]]][0]; 82 Clear(Father[Root[ID[x]]]); 83 Father[Root[ID[x]]]=0; 84 return; 85 } 86 int oldroot=Root[ID[x]]; 87 int pre=Pre(Root[ID[x]]); 88 Splay(pre); 89 Son[Root[ID[x]]][1]=Son[oldroot][1]; 90 Father[Son[oldroot][1]]=Root[ID[x]]; 91 Clear(oldroot); 92 Update(Root[ID[x]]); 93 } 94 95 void Merge(int x,int y) 96 { 97 if (Son[x][0]) Merge(Son[x][0],y); 98 if (Son[x][1]) Merge(Son[x][1],y); 99 int val=Val[x]+Add[ID[x]]-Add[ID[y]]; Clear(x); 100 Insert(x,y,val); 101 } 102 103 int main() 104 { 105 scanf("%d",&n); 106 for (int i=1; i<=n; ++i) 107 { 108 scanf("%d",&x); 109 ID[i]=i; Val[i]=x; Max[i]=x; 110 Root[i]=i; Size[i]=1; Heap.push(x); 111 } 112 scanf("%d",&m); 113 for (int i=1; i<=m; ++i) 114 { 115 scanf("%s",opt); 116 if (opt[0]=='U') 117 { 118 scanf("%d%d",&x,&y); 119 if (ID[x]!=ID[y]) 120 { 121 Del.push(min(Max[ID[x]],Max[ID[y]])); 122 if (Size[Root[ID[x]]]>Size[Root[ID[y]]]) swap(x,y); 123 Max[ID[y]]=max(Max[ID[y]],Max[ID[x]]); 124 Merge(Root[ID[x]],Root[ID[y]]); 125 } 126 } 127 128 if (opt[0]=='A' && opt[1]=='1') 129 { 130 scanf("%d%d",&x,&v); 131 int val=Val[x]+v; 132 if (Size[Root[ID[x]]]==1) 133 { 134 Val[x]=val; 135 Del.push(Max[ID[x]]); 136 Max[ID[x]]=val+Add[ID[x]]; 137 Heap.push(Max[ID[x]]); 138 continue; 139 } 140 Delete(x); Insert(x,Root[ID[x]],val); 141 Del.push(Max[ID[x]]); 142 Max[ID[x]]=Get_Max(Root[ID[x]])+Add[ID[x]]; 143 Heap.push(Max[ID[x]]); 144 } 145 146 if (opt[0]=='A' && opt[1]=='2') 147 { 148 scanf("%d%d",&x,&v), Add[ID[x]]+=v; 149 Del.push(Max[ID[x]]); 150 Max[ID[x]]=Get_Max(Root[ID[x]])+Add[ID[x]]; 151 Heap.push(Max[ID[x]]); 152 } 153 154 if (opt[0]=='A' && opt[1]=='3') 155 scanf("%d",&v),ALL+=v; 156 157 if (opt[0]=='F' && opt[1]=='1') 158 scanf("%d",&x), printf("%d\n",Val[x]+Add[ID[x]]+ALL); 159 160 if (opt[0]=='F' && opt[1]=='2') 161 { 162 scanf("%d",&x), printf("%d\n",Max[ID[x]]+ALL); 163 } 164 165 if (opt[0]=='F' && opt[1]=='3') 166 { 167 while ((!Heap.empty()) && (!Del.empty()) && Heap.top()==Del.top()) 168 Heap.pop(), Del.pop(); 169 printf("%d\n",Heap.top()+ALL); 170 } 171 } 172 }