BZOJ2333: [SCOI2011]棘手的操作
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
3
0 0 0
8
A1 3 -20
A1 2 20
U 1 3
A2 1 10
F1 3
F2 3
A3 -10
F3
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
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
随便做就行。。。
我发现我的代码能力真是喂狗了。。。。。
比如可以启发式合并连通块,用n个堆Q[i]维护连通块内的所有值,用一个堆维护所有Q[i]的堆顶。
#include<cstdio> #include<cctype> #include<queue> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=300010; struct Queue { priority_queue<int> Q,del; void push(int x) {Q.push(x);} void remove(int x) {del.push(x);} int top() { while(del.size()&&Q.top()==del.top()) Q.pop(),del.pop(); return Q.top(); } }Q[maxn],Q2; int n,val[maxn],first[maxn],next[maxn],last[maxn]; int pa[maxn],s[maxn],addv[maxn],addall; int findset(int x) {return x==pa[x]?x:pa[x]=findset(pa[x]);} void merge(int x,int y) { x=findset(x);y=findset(y); if(x==y) return;if(s[x]>s[y]) swap(x,y); pa[x]=y;s[y]+=s[x];next[last[y]]=first[x];last[y]=last[x]; Q2.remove(Q[x].top()+addv[x]);Q2.remove(Q[y].top()+addv[y]); for(int i=first[x];i;i=next[i]) { val[i]+=addv[x]-addv[y];Q[y].push(val[i]); } Q2.push(Q[y].top()+addv[y]); } int main() { n=read(); rep(i,1,n) { val[i]=read(),pa[i]=i,s[i]=1,first[i]=last[i]=i; Q[i].push(val[i]);Q2.push(val[i]); } dwn(i,read(),1) { char cmd[3];scanf("%s",cmd); if(cmd[0]=='F'&&cmd[1]=='3') printf("%d\n",addall+Q2.top()); else if(cmd[0]=='U') merge(read(),read()); else { if(cmd[0]=='F') { int x=read(),y=findset(x); if(cmd[1]=='1') printf("%d\n",val[x]+addv[y]+addall); else printf("%d\n",Q[y].top()+addv[y]+addall); } else if(cmd[1]=='3') addall+=read(); else { int x=read(),v=read(); if(cmd[1]=='1') { int y=findset(x); Q2.remove(Q[y].top()+addv[y]);Q[y].remove(val[x]);val[x]+=v; Q[y].push(val[x]);Q2.push(Q[y].top()+addv[y]); } else { x=findset(x);Q2.remove(Q[x].top()+addv[x]); addv[x]+=v;Q2.push(Q[x].top()+addv[x]); } } } } return 0; }