您的位置:首页 > 其它

bzoj3611: [Heoi2014]大工程

2016-04-11 20:56 344 查看

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3611

题意:中文题。

分析:同消耗战是一类题,询问过多,但是关键节点少,那么我们先建虚树(最大2*max个节点),同消耗战建虚树。然后在树上跑一遍DP即可。O(max*logn)

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1000100;
const int MAX=100000000;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int tot,u
,v[2*N],pre[2*N];
void add(int a,int b) {
v[tot]=b;pre[tot]=u[a];u[a]=tot++;
}
int k,in
,de
,fa
[22];
void dfs(int a,int b) {
k++;in[a]=k;
de[a]=de[b]+1;fa[a][0]=b;
for (int i=1;i<=20;i++)
if (de[a]>1<<i) fa[a][i]=fa[fa[a][i-1]][i-1];
for (int i=u[a];i!=-1;i=pre[i])
if (v[i]!=b) dfs(v[i],a);
}
ll ans,sum
;
int x
,d
,bo
,siz
;
int ans_min,ans_max,dismi
,dismx
;
int cmp(int a,int b) {
return in[a]<in[b];
}
int getlca(int a,int b) {
if (de[a]<de[b]) { a^=b;b^=a;a^=b; }
for (int i=20;i>=0;i--)
if (de[a]-(1<<i)>=de[b]) a=fa[a][i];
if (a==b) return a;
for (int i=20;i>=0;i--)
if (de[a]>1<<i&&fa[a][i]!=fa[b][i]) { a=fa[a][i];b=fa[b][i]; }
return fa[a][0];
}
void dfs_dp(int a) {
siz[a]=bo[a];
sum[a]=0;dismx[a]=0;
dismi[a]=bo[a] ? 0:MAX;
for (int i=u[a];i!=-1;i=pre[i]) {
dfs_dp(v[i]);
if (siz[a]) ans_min=min(ans_min,dismi[a]+dismi[v[i]]+de[v[i]]-de[a]);
if (siz[a]) ans_max=max(ans_max,dismx[a]+dismx[v[i]]+de[v[i]]-de[a]);
ans+=sum[a]*siz[v[i]]+sum[v[i]]*siz[a]+((ll)siz[a]*siz[v[i]])*(de[v[i]]-de[a]);
siz[a]+=siz[v[i]];
sum[a]+=sum[v[i]]+(ll)(de[v[i]]-de[a])*siz[v[i]];
dismi[a]=min(dismi[a],dismi[v[i]]+de[v[i]]-de[a]);
dismx[a]=max(dismx[a],dismx[v[i]]+de[v[i]]-de[a]);
}
u[a]=-1;
}
int main()
{
int a,b,i,n,m,q,lca;
scanf("%d", &n);
tot=0;memset(u,-1,sizeof(u));
for (i=1;i<n;i++) {
scanf("%d%d", &a, &b);
add(a,b);add(b,a);
}
k=de[1]=0;
dfs(1,1);
memset(bo,0,sizeof(bo));
tot=0;memset(u,-1,sizeof(u));
scanf("%d", &q);
while (q--) {
scanf("%d", &m);
for (i=1;i<=m;i++) {
scanf("%d", &x[i]);bo[x[i]]=1;
}
sort(x+1,x+m+1,cmp);
k=0;d[++k]=1;
for (i=1;i<=m;i++) {
lca=getlca(x[i],d[k]);
while (de[lca]<de[d[k]]) {
if (de[lca]>=de[d[k-1]]) {
add(lca,d[k]);k--;
if (d[k]!=lca) d[++k]=lca;
break ;
}
add(d[k-1],d[k]);k--;
}
if (d[k]!=x[i]) d[++k]=x[i];
}
while (--k) add(d[k],d[k+1]);
ans=0;ans_min=MAX;ans_max=0;
dfs_dp(1);
printf("%lld %d %d\n", ans, ans_min, ans_max);
for (i=1;i<=m;i++) bo[x[i]]=0;
}
return 0;
}

/*
10
2 1
3 2
4 1
5 2
6 4
7 5
8 6
9 7
10 9
8
2
3 5
3
1 2 3
3
1 2 2
2
5 4
2
10 4
2
5 2
2
6 1
2
6 1

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: