转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526 by---cxlove
题目:给出一些点,每个点有权值,然后有一些边,相连。无向的。然后有一些操作
query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大)
destory a,b 表示删除连接a,b的边
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3563
逆向并查集。
把没有删除的边先加入并查集,一个集合内表示连通的,根结点为权值最大的点。
然后对于查询离线读入,从最后开始操作,对于删除的点,然后重新加入到并查集中,更新最值。
查询的时候便是查询根结点的值是否大于自身的值
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1<<30
#define M 60005
#define N 605
#define maxn 300005
#define eps 1e-10
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson step<<1
#define rson step<<1|1
#define MOD 1000000009
#define sqr(a) ((a)*(a))
using namespace std;
struct query
{
int a,b,k;
}que[50005];
map<pair<int,int>,int>edge;
int pre[10005],num[10005],val[10005];
int n,m,q;
int find(int x)
{
if(x!=pre[x])
{
int f=pre[x];
pre[x]=find(pre[x]);
num[x]=max(num[x],num[f]);
}
return pre[x];
}
void Union(int x,int y)
{
int ra=find(x),rb=find(y);
if(ra==rb) return;
if(num[ra]>num[rb]||(num[ra]==num[rb]&&ra<rb)) pre[rb]=ra;
else pre[ra]=rb;
}
int main()
{
int first=1;
while(scanf("%d",&n)!=EOF)
{
if(!first) puts("");else first=0;
for(int i=0;i<n;i++) scanf("%d",&val[i]);
edge.clear();
scanf("%d",&m);
for(int i=0;i<n;i++) pre[i]=i,num[i]=val[i];
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(u>v) swap(u,v);
edge[mp(u,v)]=1;
}
scanf("%d",&q);
for(int i=0;i<q;i++)
{
char str[10];
scanf("%s",str);
if(str[0]=='q')
{
scanf("%d",&que[i].a);
que[i].k=0;
}
else
{
scanf("%d%d",&que[i].a,&que[i].b);
if(que[i].a>que[i].b) swap(que[i].a,que[i].b);
edge[mp(que[i].a,que[i].b)]=0;
que[i].k=1;
}
}
map<pair<int,int>,int>::iterator it;
for(it=edge.begin();it!=edge.end();it++)
{
if(it->second)
{
pair<int,int> tmp=it->first;
Union(tmp.first,tmp.second);
}
}
vector<int>ans;ans.clear();
for(int i=q-1;i>=0;i--)
{
if(que[i].k==0)
{
if(num[find(que[i].a)]<=val[que[i].a]) ans.pb(-1);
else ans.pb(find(que[i].a));
}
else Union(que[i].a,que[i].b);
}
for(int i=ans.size()-1;i>=0;i--) printf("%d\n",ans[i]);
}
return 0;
}