您的位置:首页 > 其它

[BZOJ3572][HNOI2014]世界树

2016-03-04 21:54 429 查看
这一题调试了蛮久,而且我一写虚树常数就大,是rank1的17倍。

显然是一道虚树题。建出虚树后,先两遍DFS处理出每个虚树上的点的归属,然后考虑虚树每一条边的贡献。

定义sizesize为原树每个子树大小

对于一条边(u,v)(u,v),设xx为原树中uu的儿子vv的祖先。

若bel[u]=bel[v]bel[u]=bel[v],ans[bel[u]]+=size[x]−size[v]ans[bel[u]]+=size[x]-size[v]

否则,在原树u→vu\rightarrow v链上二分一个点midmid,使midmid下面的点属于bel[v]bel[v],上面的属于bel[u]bel[u],ans[bel[u]]+=size[x]−size[mid],ans[bel[v]]+=size[mid]−size[v]ans[bel[u]]+=size[x]-size[mid],ans[bel[v]]+=size[mid]-size[v],最后还要处理不在虚树上的子树,这些子树一定隶属它在虚树上的根的管辖,记一个remrem数组维护这些子树大小即可。

妈的调了3个小时的jg题。我不做工业题谁做工业题。

#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
#include<climits>
#define X first
#define Y second
#define DB double
#define lc now<<1
#define rc now<<1|1
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
template<typename T>void Read(T& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
const int MAXN=601000;
int n,m,k,h[MAXN],ans[MAXN],pa[MAXN],iskey[MAXN];
int A[MAXN],size_a=0;
int dep[MAXN],fa[MAXN][20],bel[MAXN],dfn[MAXN],size[MAXN],rem[MAXN];
pii clo[MAXN];
struct Tree{
int e,dfs_clock,first[MAXN],next[MAXN],to[MAXN];
void init()
{
memset(first,0,sizeof(first));
e=dfs_clock=0;
}
void add(int u,int v)
{//if you judge i==0 instead of i==-1 ++e first
++e;next[e]=first[u];first[u]=e;to[e]=v;
++e;next[e]=first[v];first[v]=e;to[e]=u;
}
void dfs(int u,int f)
{
if(u==1)dep[u]=1;
else dep[u]=dep[f]+1;
fa[u][0]=f;
size[u]=1;
dfn[u]=++dfs_clock;
for(int i=1;i<20;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=first[u];i;i=next[i])
{
int v=to[i];
if(v==f)continue;
dfs(v,u);
size[u]+=size[v];
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
if(!y)return y;
for(int i=18;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)return x;
for(int i=18;i>=0;i--)
if(fa[x][i]&&fa[y][i]&&fa[x][i]!=fa[y][i])
x=fa[x][i],
y=fa[y][i];
return fa[x][0];
}
}ori,vit;
int dis(int u,int v)
{
return dep[u]+dep[v]-2*dep[ori.LCA(u,v)];
}
void dfs1(int u,int f)
{
rem[u]=size[u];
for(int i=vit.first[u];i;i=vit.next[i])
{
int v=vit.to[i];
if(v==f)continue;
if(u!=0)
{
int D=dis(u,v);
if(clo[v].X>clo[u].X+D)//> instead of <
clo[v].Y=clo[u].Y,
clo[v].X=clo[u].X+D;
else if(clo[v].X==clo[u].X+D)//NO judging
if(clo[u].Y<clo[v].Y)
clo[v].Y=clo[u].Y;
}
dfs1(v,u);
}
bel[u]=clo[u].Y;
}
void dfs2(int u,int f)
{
for(int i=vit.first[u];i;i=vit.next[i])
{
int v=vit.to[i];
if(f==v)continue;
dfs2(v,u);
int D=dis(u,v);
if(clo[u].X>clo[v].X+D)
{
clo[u].X=clo[v].X+D;
clo[u].Y=clo[v].Y;
}
else if(clo[u].X==clo[v].X+D&&clo[v].Y<clo[u].Y)
{
clo[u].X=clo[v].X+D;
clo[u].Y=clo[v].Y;
}
}
}
void fuck(int u,int v)//algorithm error
{
int mid=v,a=v;
for(int i=18;i>=0;i--)
if(fa[a][i]&&dep[fa[a][i]]>dep[u])
a=fa[a][i];
rem[u]-=size[a];
if(bel[u]==bel[v])
{
ans[bel[u]]+=size[a]-size[v];
return;
}
for(int i=18;i>=0;i--)
if(fa[mid][i]&&dis(fa[mid][i],bel[u])>dis(fa[mid][i],bel[v]))
mid=fa[mid][i];
if(dis(fa[mid][0],bel[u])==dis(fa[mid][0],bel[v]))
if(bel[u]>bel[v])
mid=fa[mid][0];
ans[bel[v]]+=size[mid]-size[v];
ans[bel[u]]+=size[a]-size[mid];
}
void work(int u,int f)
{
if(f==0)
ans[bel[u]]+=n-size[u];
for(int i=vit.first[u];i;i=vit.next[i])
{
int v=vit.to[i];
if(v==f)continue;
if(u!=0)
fuck(u,v);
work(v,u);
}
ans[bel[u]]+=rem[u];
}
int top,st[MAXN];
bool cmp(const int& x,const int& y)
{
return dfn[x]<dfn[y];
}
void solve()
{
size_a=0;
vit.init();
top=0;
st[++top]=0;
sort(h+1,h+k+1,cmp);
for(int i=1;i<=k;i++)
{
int x=ori.LCA(st[top],h[i]);
A[size_a++]=x;
A[size_a++]=h[i];
for(;dep[st[top]]>dep[x];--top)
if(dep[st[top-1]]<=dep[x])
pa[st[top]]=x;
if(x!=st[top])
{
pa[x]=st[top];
st[++top]=x;
}
pa[st[++top]=h[i]]=x;
}
sort(A,A+size_a);
size_a=unique(A,A+size_a)-A;
for(int i=0;i<size_a;i++)
vit.first[A[i]]=0;
for(int i=0;i<size_a;i++)
{
if(A[i]==0)continue;
//DEBUG("%d %d\n",A[i],pa[A[i]]);
vit.add(A[i],pa[A[i]]);
}
clo[0].X=INF;
for(int i=0;i<size_a;i++)
if(iskey[A[i]])
clo[A[i]].X=0,clo[A[i]].Y=A[i];
else
clo[A[i]].X=INF;
dfs2(0,0);//dfs2 first!
dfs1(0,0);
work(0,-1);
}
int tmp[MAXN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
#endif
ori.init();
Read(n);
for(int i=1;i<n;i++)
{
int a,b;
Read(a);Read(b);
ori.add(a,b);
}
ori.dfs(1,0);
Read(m);
for(int i=1;i<=m;i++)
{
Read(k);
for(int j=1;j<=k;j++)
Read(h[j]),iskey[h[j]]=1;
memcpy(tmp,h,sizeof(int)*(k+1));
solve();
for(int j=1;j<=k;j++)
{
printf("%d ",ans[tmp[j]]==0?1:ans[tmp[j]]);
iskey[tmp[j]]=ans[tmp[j]]=0;
}
puts("");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: