题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2333
题目大意:对于一幅图支持7种操作(详见原题)。
算法讨论:
通过U x y、F2 x和F3操作,我们发现题目既要求最大值又要支持合并操作,我们可以想到用可并堆进行维护。
可并堆?如果你愿意的话显然配对堆和Fibonacci堆是很优秀的……但是我用的是斜堆(同学们想想代码复杂度吧……)
由于既要维护连通块的Max和全局的Max,我们需要开2个堆,一个是维护当前连通块的Max,另一个维护全局的Max。
在全局的Max中我们只要维护每个连通块堆顶值的Max就可以了,因为每个连通块堆顶的Max一定比该连通块中的其他值更优。
对于F2操作,我们可以先通过不断地找父亲找到x点的祖先,然后用类似于线段树Lazy的思想进行处理。
对于A1和A2操作,我们可以先在堆中把相应节点删除,进行相应操作后再添加到堆中。
在堆的合并操作时,我们可以顺带地把Lazy标记下传。
在删除节点时,我们需要把其祖先们的Lazy标记累加,因为下一次合并到堆中时一定是标记下传在合并之前进行。相似地,F1操作也需要把其祖先们的Lazy标记累加。
至于A3这种操作……只需要在全局设个变量记录一下就可以了。
一题又这么A掉了……
Code:
/*
* Problem:2333
* Author:PYC
*/
#include <cstdio>
#include <queue>
#include <algorithm>
#define maxn 300000
using namespace std;
char s[10];
int n,m,root,add;
struct node{
int key,l,r,fa,add;
}heap1[maxn*2+1],heap2[maxn*2+1];
void down(int x){
heap1[heap1[x].l].key+=heap1[x].add;
heap1[heap1[x].l].add+=heap1[x].add;
heap1[heap1[x].r].key+=heap1[x].add;
heap1[heap1[x].r].add+=heap1[x].add;
heap1[x].add=0;
}
int fa(int x){
int tmp=x;
while (heap1[tmp].fa) tmp=heap1[tmp].fa;
return tmp;
}
int sum(int x){
int tmp=x,sum=0;
while (tmp=heap1[tmp].fa) sum+=heap1[tmp].add;
return sum;
}
int merge1(int x,int y){
if (!x || !y) return x?x:y;
if (heap1[x].key<heap1[y].key) swap(x,y);
down(x);
heap1[x].r=merge1(heap1[x].r,y);
heap1[heap1[x].r].fa=x;
swap(heap1[x].l,heap1[x].r);
return x;
}
int merge2(int x,int y){
if (!x || !y) return x?x:y;
if (heap2[x].key<heap2[y].key) swap(x,y);
heap2[x].r=merge2(heap2[x].r,y);
heap2[heap2[x].r].fa=x;
swap(heap2[x].l,heap2[x].r);
return x;
}
int del1(int x){
down(x);
int y=merge1(heap1[x].l,heap1[x].r);
if (x==heap1[heap1[x].fa].l) heap1[heap1[x].fa].l=y;else heap1[heap1[x].fa].r=y;
heap1[y].fa=heap1[x].fa;
return fa(y);
}
void del2(int x){
int y=merge2(heap2[x].l,heap2[x].r);
if (root==x) root=y;
if (x==heap2[heap2[x].fa].l) heap2[heap2[x].fa].l=y;else heap2[heap2[x].fa].r=y;
heap2[y].fa=heap2[x].fa;
}
void renew1(int x,int v){
heap1[x].key=v;
heap1[x].fa=heap1[x].l=heap1[x].r=0;
}
void renew2(int x,int v){
heap2[x].key=v;
heap2[x].fa=heap2[x].l=heap2[x].r=0;
}
int heapify(){
queue<int> Q;
for (int i=1;i<=n;++i) Q.push(i);
while (Q.size()>1){
int x=Q.front();Q.pop();
int y=Q.front();Q.pop();
Q.push(merge2(x,y));
}
return Q.front();
}
void U(){
int x,y;scanf("%d%d",&x,&y);
int fx=fa(x),fy=fa(y);
if (fx!=fy) if (merge1(fx,fy)==fx) del2(fy);else del2(fx);
}
void A1(){
int x,v;scanf("%d%d",&x,&v);
del2(fa(x));
int y=del1(x);
renew1(x,heap1[x].key+v+sum(x));
int z=merge1(y,x);
renew2(z,heap1[z].key);
root=merge2(root,z);
}
void A2(){
int x,v,y;scanf("%d%d",&x,&v);
del2(y=fa(x));
heap1[y].key+=v;
heap1[y].add+=v;
renew2(y,heap1[y].key);
root=merge2(root,y);
}
void A3(){
int v;scanf("%d",&v);
add+=v;
}
void F1(){
int x;scanf("%d",&x);
printf("%d\n",heap1[x].key+sum(x)+add);
}
void F2(){
int x;scanf("%d",&x);
printf("%d\n",heap1[fa(x)].key+add);
}
void F3(){
printf("%d\n",heap2[root].key+add);
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&heap1[i].key),heap2[i].key=heap1[i].key;
root=heapify();
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%s",s);
if (s[0]=='U') U();
if (s[0]=='A'){
if (s[1]=='1') A1();
if (s[1]=='2') A2();
if (s[1]=='3') A3();
}
if (s[0]=='F'){
if (s[1]=='1') F1();
if (s[1]=='2') F2();
if (s[1]=='3') F3();
}
}
return 0;
}
By Charlie Pan
Mar 9,2014