您的位置:首页 > 其它

bzoj 4530: [Bjoi2014]大融合

2016-05-18 20:13 246 查看
先说一下我的做法:没有强制在线,先建出来这棵树,然后发现x到它父亲的边的答案是 (目前连通块大小-x子树的大小)*(x子树的大小),这个子树大小也是指目前连通块内的子树大小,子树大小可以用线段树维护dfs序,进行线段树合并得到。子树size也可以用树链剖分做。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define N 100010
using namespace std;
struct yts { int x,t,ne;} e[2*N];
int left[N],right[N],fa[N],dep[N],v[N],root[N];
int dfs_cnt=0;
int cnt=0,num=0;
int ch[N*20][2],sz[N*20];
char st[N];
struct QQ { int x,y;} q[N];
int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]);}
void put(int x,int y)
{
num++; e[num].x=x; e[num].t=y;
e[num].ne=v[x]; v[x]=num;
}
 
void dfs(int x,int fa)
{
left[x]=++dfs_cnt;
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].t;
if (y!=fa)
{
dep[y]=dep[x]+1;
dfs(y,x);
}
}
right[x]=dfs_cnt;
}
 
void insert(int &i,int l,int r,int x)
{
i=++cnt; sz[i]=1;
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) insert(ch[i][0],l,mid,x);
else insert(ch[i][1],mid+1,r,x);
}
 
int merge(int x,int y)
{
if (!x) return y;
if (!y) return x;
sz[x]+=sz[y];
ch[x][0]=merge(ch[x][0],ch[y][0]);
ch[x][1]=merge(ch[x][1],ch[y][1]);
return x;
}
 
ll query(int i,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) return sz[i];
int mid=(l+r)>>1;
if (qr<=mid) return query(ch[i][0],l,mid,ql,qr);
if (mid+1<=ql) return query(ch[i][1],mid+1,r,ql,qr);
return query(ch[i][0],l,mid,ql,qr)+query(ch[i][1],mid+1,r,ql,qr);
}
 
int main()
{
int n,Q;
scanf("%d%d",&n,&Q);
for (int i=1;i<=Q;i++)
{
scanf("%s%d%d",st+i,&q[i].x,&q[i].y);
if (st[i]=='A') { put(q[i].x,q[i].y); put(q[i].y,q[i].x);}
}
for (int i=1;i<=n;i++)
if (!dep[i])
{
dep[i]=1; dfs(i,0);
}
for (int i=1;i<=n;i++) { fa[i]=i; insert(root[i],1,n,left[i]);}
for (int i=1;i<=Q;i++)
if (st[i]=='A')
{
int x=find(q[i].x),y=find(q[i].y);
if (dep[x]>dep[y]) swap(x,y);
root[x]=merge(root[x],root[y]);
fa[y]=x;
}
else
{
int x=q[i].x,y=q[i].y,z=find(x);
if (dep[x]<dep[y]) x=y;
ll ans=query(root[z],1,n,left[x],right[x]);
printf("%d\n",(sz[root[z]]-ans)*ans);
}
return 0;
}
//py
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: