UOJ14 UER #1 DZY Loves Graph(最小生成树+并查集)

  显然可以用可持久化并查集实现。考虑更简单的做法。如果没有撤销操作,用带撤销并查集暴力模拟即可,复杂度显然可以均摊。加上撤销操作,删除操作的复杂度不再能均摊,但注意到我们在删除时就可以知道他会不会被撤销,所以遇到一个要被撤销的删除操作时,直接求出去掉k条边后的MST即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
#define M 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,m,fa[N],size[N],e[M],cnt,top;
char qwerty[10];
ll ans;
struct data{int op,x,y;
}q[M];
struct data2{int x,fa,s,i;ll sum;
}stk[N<<1];
int find(int x){return fa[x]==x?x:find(fa[x]);}
int merge(int x,int y,int i)
{
	x=find(x),y=find(y);
	if (x==y) return 0;
	if (size[x]<size[y]) swap(x,y);
	top++;stk[top].x=x;stk[top].fa=fa[x];stk[top].s=size[x];stk[top].i=i;stk[top].sum=stk[top-1].sum+i;
	top++;stk[top].x=y;stk[top].fa=fa[y];stk[top].s=size[y];stk[top].i=i;stk[top].sum=stk[top-1].sum+i;
	size[x]+=size[y],fa[y]=x;
	return i;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	const char LL[]="%I64d\n";
#else
	const char LL[]="%lld\n";
#endif
	n=read(),m=read();
	for (int i=1;i<=m;i++)
	{
		char c=getc();
		if (c=='A') q[i].op=0,q[i].x=read(),q[i].y=read();
		if (c=='D') q[i].op=1,q[i].x=read();
		if (c=='R') q[i].op=2,cin>>qwerty;
	}
	for (int i=1;i<=n;i++) fa[i]=i,size[i]=1;
	for (int i=1;i<=m;i++)
	{
		if (q[i].op==0) ans+=merge(q[i].x,q[i].y,i),e[++cnt]=i;
		if (q[i].op==1)
		{
			int l=1,r=top,u=0;
			while (l<=r)
			{
				int mid=l+r>>1;
				if (stk[mid].i<=e[cnt-q[i].x]) u=mid,l=mid+1;
				else r=mid-1;
			}
			ans=stk[u].sum>>1;
			if (q[i+1].op!=2)
			{
				cnt-=q[i].x;
				while (stk[top].i>e[cnt]) fa[stk[top].x]=stk[top].fa,size[stk[top].x]=stk[top].s,top--;
			}
		}
		if (q[i].op==2)
		{
			if (q[i-1].op==0)
			{
				int x=0;
				while (stk[top].i==i-1) fa[stk[top].x]=stk[top].fa,size[stk[top].x]=stk[top].s,x+=stk[top].i,top--;
				ans-=x>>1;cnt--;
			}
			else ans=stk[top].sum/2;
		}
		if (top==(n-1<<1)&&ans==stk[top].sum/2) printf(LL,ans);
		else printf("0\n");
		//for (int j=1;j<=cnt;j++) cout<<e[j]<<' ';cout<<endl;
		//for (int j=2;j<=top;j+=2) cout<<stk[j].i<<' '<<stk[j].sum/2<<endl;
		//cout<<endl;
	}
	return 0;
}

 

  

 

posted @ 2019-04-19 21:14  Gloid  阅读(210)  评论(0编辑  收藏  举报