发现对于任意一条边,起决定性作用的是节点编号更大的点.
于是,对于每一条边,按照节点编号较大值作为边权,按照最小生成树的方式插入即可.
最后用线段树维护 dfs 序做一个区间查询即可.
Code:
#include <bits/stdc++.h> #define N 400005 #define ll long long #define mod 998244353 #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll val[N],mul[N<<2],V[N]; int n,m,Q,tot,edges,tt; int p[N],cc[N],hd[N],to[N],nex[N],dfn[N],st[N],ed[N],size[N],Fa[21][N],F[21][N]; struct Edge { int u,v,c; Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){} }e[N]; void pushup(int l,int r,int now) { ll re=1; int mid=(l+r)>>1; if(l<=mid)re=re*mul[now<<1]%mod; if(r>mid) re=re*mul[now<<1|1]%mod; mul[now]=re; } void build(int l,int r,int now) { if(l==r) { mul[now]=V[l]%mod; return; } int mid=(l+r)>>1; if(l<=mid) build(l,mid,now<<1); if(r>mid) build(mid+1,r,now<<1|1); pushup(l,r,now); } void update(int l,int r,int now,int p,int v) { if(l==r) { V[l]=mul[now]=1ll*v%mod; return; } int mid=(l+r)>>1; if(p<=mid) update(l,mid,now<<1,p,v); else update(mid+1,r,now<<1|1,p,v); pushup(l,r,now); } ll query(int l,int r,int now,int L,int R) { if(l>=L&&r<=R) return mul[now]; ll re=1; int mid=(l+r)>>1; if(L<=mid) re=re*query(l,mid,now<<1,L,R)%mod; if(R>mid) re=re*query(mid+1,r,now<<1|1,L,R)%mod; return re; } int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } bool cmp(Edge a,Edge b) { return a.c<b.c; } void addedge(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs(int u,int ff) { st[u]=dfn[u]=++tt, size[u]=1, V[dfn[u]]=val[u]; Fa[0][u]=ff, F[0][u]=max(cc[ff], cc[u]); for(int i=1;i<=20;++i) { Fa[i][u]=Fa[i-1][Fa[i-1][u]]; F[i][u]=max(F[i-1][u], F[i-1][Fa[i-1][u]]); } for(int i=hd[u];i;i=nex[i]) { int v=to[i]; dfs(v, u); size[u]+=size[v]; } ed[u]=tt; } int get(int x,int k) { for(int i=20;i>=0;--i) if(Fa[i][x] && F[i][x] <= k) x=Fa[i][x]; return x; } int main() { int i,j,k; // setIO("input"); scanf("%d%d%d",&n,&m,&Q); tot=n; for(i=1;i<N;++i) p[i]=i; for(i=1;i<=n;++i) scanf("%lld",&val[i]),cc[i]=i; for(i=1;i<=m;++i) { scanf("%d%d",&e[i].u,&e[i].v); e[i].c=max(e[i].u, e[i].v); } sort(e+1,e+1+m,cmp); for(i=1;i<=m;++i) { int u=e[i].u, v=e[i].v; int x=find(u),y=find(v); if(x!=y) { ++tot; val[tot]=1ll; cc[tot]=e[i].c; p[x]=tot,p[y]=tot; addedge(tot,x), addedge(tot,y); } } cc[0]=1000000000; dfs(tot,0); build(1,tot,1); for(i=1;i<=Q;++i) { int op; scanf("%d",&op); if(op==1) { int x,y; scanf("%d%d",&x,&y); if(x>y) printf("0 "); else { int k=get(x,y); int L=st[k], R=ed[k]; printf("%lld ",query(1,tot,1,L,R)); } } if(op==2) { int x,y; scanf("%d%d",&x,&y); update(1,tot,1,dfn[x],y); } } return 0; }