比较好的一个题
Description
支持连边和查询一条边两端的连通块的大小乘积的数据结构
Solution
原来是用 (LCT) 做的,现在用线段树合并上上
连接两条边不就是 (merge) 一下
(merge) 啥就是了个问题
直接 (dfs) 序上面连续的树的编号就比较可做了
每次搞是不能整出来 (dfs) 序的,那就离线呗
先处理出来 (dfs) 序,查询的时候标号就连续了
权值线段树存标号,所在标号的 (val) 为 (1)
这题的费时:没有想明白权值线段树存什么(真的是阴沟翻船,并查集 (+) 离线都想出来了)
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=1e5+10,M=5e6+10;
struct node{
int to,nxt;
}e[N<<1];
int head[N],cnt,n,T;
inline void add(int u,int v)
{
e[++cnt].to=v; e[cnt].nxt=head[u];
return head[u]=cnt,void();
}
int ls[M],rs[M],val[M],tot;
inline void push_up(int x){return val[x]=val[ls[x]]+val[rs[x]],void();}
inline void build(int &p,int l,int r,int x)
{
if(!p) p=++tot; if(l==r) return val[p]++,void();
int mid=(l+r)>>1;
if(x<=mid) build(ls[p],l,mid,x);
else build(rs[p],mid+1,r,x);
return push_up(p);
}
inline int merge(int x,int y,int l,int r)
{
if(!x||!y) return x+y;
int p=++tot,mid=(l+r)>>1;
ls[p]=merge(ls[x],ls[y],l,mid);
rs[p]=merge(rs[x],rs[y],mid+1,r);
return push_up(p),p;
}
inline int ask(int x,int l,int r,int st,int ed)
{
if(l<=st&&ed<=r) return val[x];
int ans=0,mid=(st+ed)>>1;
if(l<=mid) ans+=ask(ls[x],l,r,st,mid);
if(r>mid) ans+=ask(rs[x],l,r,mid+1,ed);
return ans;
}
bool vis[N]; int in[N],out[N],tim,id[N],dep[N];
inline void dfs(int x,int fa)
{
in[x]=++tim; vis[x]=1; id[tim]=x; dep[x]=dep[fa]+1;
for(int i=head[x];i;i=e[i].nxt)
{
int t=e[i].to; if(t==fa) continue;
dfs(t,x);
}out[x]=tim;
return ;
}
string opt[N]; int x[N],y[N],fa[N],rt[N];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
signed main()
{
n=read(); T=read();
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1;i<=T;++i)
{
cin>>opt[i];
x[i]=read(); y[i]=read();
if(opt[i][0]=='A') add(x[i],y[i]),add(y[i],x[i]);
}
int anc=n+1;
for(int i=1;i<=n;++i)
{
if(!in[i]) tim=0,dfs(i,0);
}
for(int i=1;i<=n;++i) build(rt[i],1,n,in[i]);
for(int i=1;i<=T;++i)
{
if(opt[i][0]=='A')
{
x[i]=find(x[i]); y[i]=find(y[i]);
rt[x[i]]=merge(rt[x[i]],rt[y[i]],1,n);
fa[y[i]]=x[i];
}
if(opt[i][0]=='Q')
{
if(dep[x[i]]<dep[y[i]]) swap(x[i],y[i]);
y[i]=find(y[i]);
printf("%lld
",(ask(rt[y[i]],1,in[x[i]]-1,1,n)+ask(rt[y[i]],out[x[i]]+1,n,1,n))*ask(rt[y[i]],in[x[i]],out[x[i]],1,n));
}
}
return 0;
}
}
signed main(){return yspm::main();}