题目1:CodeForces 1417 F Graph and Queries
对于一个无向图联通块内找最大值问题可以用并查集dfs序线段树来解决 但是这个题目存在删边操作 那么我们就把删边变为加边 对题目删除的边逆着进行克鲁斯卡尔重构树 即将两个节点的祖节点都连接在一个新点上 这样可以连通块内的点都是这个祖的子树节点 可以使用dfs序来解决
#include <iostream>
#include <cstdio>
const int maxm=1e6+100;
struct node{
int u,v;
}edge[maxm];
struct Node{
int opt,x;
}query[maxm];
int head[maxm],to[maxm*2],net[maxm*2],mat[maxm],cnt,tot;
bool used[maxm];
int val[maxm],dfn[maxm],pos[maxm],siz[maxm],fa[maxm];
int n,m,q;
inline void addedge(int u,int v)
{
to[++cnt]=v,net[cnt]=head[u],head[u]=cnt;
}
struct Pos{
int maxi,id;
}st[maxm*4];
inline Pos merge(Pos x1,Pos x2)
{
if(x1.maxi>x2.maxi) return x1;
else return x2;
}
inline void pushup(int o){st[o]=merge(st[(o<<1)],st[(o<<1)|1]);}
void build(int o,int l,int r)
{
if(l>=r)
{
st[o]=(Pos){val[dfn[l]],l};
return;
}
int mid=(l+r)>>1;
build((o<<1),l,mid),build((o<<1)|1,mid+1,r);
pushup(o);
}
void change(int o,int l,int r,int ind)
{
if(l>=r)
{
st[o].maxi=0;
return;
}
int mid=(l+r)>>1;
ind<=mid?change((o<<1),l,mid,ind):change((o<<1)|1,mid+1,r,ind);
pushup(o);
}
Pos ask(int o,int l,int r,int ql,int qr)
{
if(ql>r||qr<l) return (Pos){-1,-1};
if(ql<=l&&r<=qr) return st[o];
int mid=(l+r)>>1;
return merge(ask((o<<1),l,mid,ql,qr),ask((o<<1)|1,mid+1,r,ql,qr));
}
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void dfs(int x)
{
pos[x]=++tot,dfn[tot]=x,siz[x]=1;
for(int i=head[x];i;i=net[i])
{
dfs(to[i]);
siz[x]+=siz[to[i]];
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=m;i++) scanf("%d%d",&edge[i].u,&edge[i].v);
for(int i=1;i<=q;i++)
{
scanf("%d%d",&query[i].opt,&query[i].x);
if(query[i].opt==2) used[query[i].x]=1;
}
for(int i=1;i<=n+m;i++) fa[i]=i;
for(int i=1;i<=m;i++)
if(!used[i])
{
int fa1=find(edge[i].u),fa2=find(edge[i].v);
if(fa1==fa2) continue;
fa[fa1]=fa2;
addedge(fa2,fa1);
}
for(int i=q;i>=1;i--)
{
if(query[i].opt==2)
{
int fa1=find(edge[query[i].x].u),fa2=find(edge[query[i].x].v);
if(fa1==fa2) continue;
n++;
fa[fa1]=n,fa[fa2]=n;
addedge(n,fa1),addedge(n,fa2);
}
else mat[i]=find(query[i].x);
}
for(int i=1;i<=n;i++)
if(!pos[i]) dfs(find(i));
build(1,1,tot);
for(int i=1;i<=q;i++)
if(query[i].opt==1)
{
Pos ans=ask(1,1,tot,pos[mat[i]],pos[mat[i]]+siz[mat[i]]-1);
if(ans.maxi) change(1,1,tot,ans.id);
printf("%d\n",ans.maxi);
}
return 0;
}