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
相关文章推荐
- Bridging Qemu Image To Real Network Using Tap Interface
- Java程序内存分析:使用mat工具分析内存占用
- Linux 开机启动软件配置和环境变量配置
- bzoj4592: [Shoi2015]脑洞治疗仪
- linux shell script脚本判断mysql是否正常启动
- VMware Workstation装windowsXP与主机形成局域网
- 慕课网二次学习(一)
- 自定义了一个view 但是无法响应事件
- 12563 - Jin Ge Jin Qu hao——[DP递推]
- 活动的最佳实践之 如何知晓当前是在哪个活动 --16
- C语言求最小公倍数和最大公约数三种算法
- 动态规划解决0/1背包问题
- Eclipse Memory Analyzer 使用技巧
- bzoj 3211 花神游历各国
- 学习SpringMVC(十)之确定目标方法POJO类型参数
- ScrollView包裹ListView
- 2016.03.06培训日记
- nyoj 1085 数单词
- 我的第一篇博文,关于震电效应的
- android-studio使用真机调试