您的位置:首页 > 产品设计 > UI/UE

[UER #1C]Dzy Loves Graph

2016-07-03 08:26 411 查看

题目大意

有n个结点,初始没有边。m个操作,操作类型有三:

1、a与b之间连一条长度为i的边(i为操作编号)

2、删除比边权最大的k条边。

3、撤销刚刚执行的操作,保证撤销的不是撤销操作。

每次操作后输出最小生成树所有边权和。

可持久化并查集

有许多版本,于是我们发现版本之间形成树的结构,为什么?

加入的边越来越大,因此删除操作相当于跳到k级祖先,每次添加操作就在下面加一个儿子,所以是树的结构。

撤销也很容易,直接看i-2所在版本即可。

我们维护并查集,如果加入的边的两端点在同一集合,由于是最小生成树,而新加入这边一定边权最大,所以不需要更新答案。

于是我们可以维护可持久化并查集。

至于跳到祖先,可以每加入一个点就处理一下倍增数组。

程序其实是非AC代码QAQ

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=300000+10,maxm=500000+10;
int fa[maxm][25],last[maxm],data[maxm],cnt[maxm],wz[maxm];
int left[maxm*6],right[maxm*6],key[maxm*6],root[maxm];
int i,j,k,l,t,n,m,tot,top,now;
char ch;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
char get(){
char ch=getchar();
while (ch!='A'&&ch!='D'&&ch!='R') ch=getchar();
return ch;
}
int newnode(int x){
top++;
left[top]=left[x];
right[top]=right[x];
key[top]=key[x];
return top;
}
void change(int &x,int l,int r,int a,int b){
x=newnode(x);
if (l==r){
key[x]=b;
return;
}
int mid=(l+r)/2;
if (a<=mid) change(left[x],l,mid,a,b);else change(right[x],mid+1,r,a,b);
}
int query(int x,int l,int r,int a){
if (l==r) return key[x];
int mid=(l+r)/2;
if (a<=mid) return query(left[x],l,mid,a);else return query(right[x],mid+1,r,a);
}
int getfa(int id,int x){
int f=query(root[id],1,n,x);
if (f==0) return x;
f=getfa(id,f);
change(root[id],1,n,x,f);
return f;
}
int getfather(int x,int y){
int j=floor(log(m)/log(2));
while (j>=0){
if ((1<<j)<=y){
y-=(1<<j);
x=fa[x][j];
}
j--;
}
return x;
}
int main(){
freopen("dzy.in","r",stdin);
n=read();m=read();
fo(i,1,m){
ch=get();
if (ch=='A'){
++tot;
fa[tot][0]=now;
data[tot]=data[now];
cnt[tot]=cnt[now];
root[tot]=root[now];
now=tot;
fo(j,1,floor(log(m)/log(2))) fa[tot][j]=fa[fa[tot][j-1]][j-1];
j=read();k=read();
j=getfa(tot,j);
k=getfa(tot,k);
if (j!=k){
change(root[tot],1,n,j,k);
data[tot]+=i;
cnt[tot]++;
}
}
else if (ch=='D'){
k=read();
now=getfather(now,k);
}
else if (ch=='R') now=wz[i-2];
if (cnt[now]==n-1) printf("%d\n",data[now]);else printf("0\n");
wz[i]=now;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: