【题解】HNOI2014世界树
脑子不清醒的时候千万别写题。写题写不下去了千万别死扛,重构才是你唯一的出路QAQ
昨天很想快点写道题,思路没有很清晰的时候就写了,结果……今天一怒之下决定重整思路重构代码,其实不过是半个小时的事情……
提示很明显,总点数限制了范围。建立出虚树,在虚树上面 dp。 在虚树上面我们dp两遍,两遍一起处理出每一个(虚树上的)节点被谁管辖,在连接两者的路径上找到管理的分界点即可。处理两点之间的距离一定要上 ST 表啊……
#include <bits/stdc++.h>
using namespace std;
#define maxn 350000
#define CNST 20
int n, dep[maxn], gra[maxn][CNST];
int size[maxn], hson[maxn], ans[maxn];
int top, S[maxn], a[maxn], b[maxn];
int timer, dfn[maxn], sum[maxn];
bool mark[maxn], vis[maxn];
int T, Log[maxn * 2], bit[21], ST[maxn * 2][CNST], pos[maxn]; int read()
{
int x = 0, k = 1;
char c;
c = getchar();
while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * k;
} struct edge
{
int cnp, to[maxn * 2], last[maxn * 2], head[maxn];
edge() { cnp = 1; }
void add(int u, int v)
{
if(u == v) return;
to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
}
}E1, E2; bool cmp(int x, int y) { return dfn[x] < dfn[y]; } void dfs(int u, int fa)
{
size[u] = 1; dfn[u] = ++ timer;
gra[u][0] = fa; dep[u] = dep[fa] + 1; ST[++ T][0] = dep[u]; pos[u] = T;
for(int i = 1; i < CNST; i ++) gra[u][i] = gra[gra[u][i - 1]][i - 1];
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(v == fa) return;
dfs(v, u); size[u] += size[v];
ST[++ T][0] = dep[u];
}
} int LCA(int x, int y)
{
if(dep[x] < dep[y]) swap(x, y);
for(int i = CNST - 1; ~i; i --)
if(dep[gra[x][i]] >= dep[y]) x = gra[x][i];
for(int i = CNST - 1; ~i; i --)
if(gra[x][i] != gra[y][i]) x = gra[x][i], y = gra[y][i];
return (x == y) ? x : gra[x][0];
} int Get_Dis(int x, int y)
{
int ret = dep[x] + dep[y];
if(!x) return dep[y]; else if(!y) return dep[x];
x = pos[x], y = pos[y];
if(x > y) swap(x, y);
int k = Log[y - x + 1];
ret = ret - 2 * min(ST[x][k], ST[y - bit[k] + 1][k]);
return ret;
} int Get_Gra(int x, int y)
{
for(int i = CNST - 1; ~i; i --)
if(dep[gra[x][i]] > dep[y]) x = gra[x][i];
return x;
} int Work(int u, int v, int k)
{
bool flag = 0;
int x = u;
for(int i = CNST - 1; i >= 0; i --)
{
int tem = gra[x][i]; if(dep[tem] < dep[k]) continue;
int d1 = Get_Dis(u, tem), d2 = Get_Dis(v, tem);
if(d1 < d2) x = gra[x][i];
else if(d1 == d2 && u < v) x = gra[x][i];
}
return x;
} void DP(int u, int fa)
{
hson[u] = 0; sum[u] = 0;
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i]; if(!v) continue;
if(v == fa) continue;
DP(v, u);
int t = hson[v];
int dis = Get_Dis(u, t), dis2 = Get_Dis(u, hson[u]);
if(dis < dis2) hson[u] = t;
else if(dis == dis2 && t < hson[u]) hson[u] = t;
if(!hson[u]) hson[u] = t;
}
if(mark[u]) hson[u] = u;
} void DP2(int u, int fa)
{
int tot = 0;
if(hson[fa])
{
int t = hson[fa];
int dis = Get_Dis(u, t), dis2 = Get_Dis(u, hson[u]);
if(dis < dis2) hson[u] = t;
else if(dis == dis2 && t < hson[u]) hson[u] = t;
if(!hson[u]) hson[u] = t;
}
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v == fa) continue; DP2(v, u);
int y = Get_Gra(v, u);
int x = Work(hson[v], hson[u], u);
int tem = size[x] - size[v];
ans[hson[v]] += tem, ans[hson[u]] += size[y] - size[x];
tot += size[y];
}
ans[hson[u]] += size[u] - tot;
E2.head[u] = 0;
} void Solve()
{
int K = read();
for(int i = 1; i <= K; i ++) b[i] = a[i] = read(), mark[a[i]] = 1;
sort(a + 1, a + 1 + K, cmp); S[top = 1] = 1; E2.cnp = 1; ans[0] = 0;
for(int i = 1; i <= K; i ++)
{
int lca = LCA(S[top], a[i]);
while(2333)
{
if(dep[S[top - 1]] <= dep[lca])
{
E2.add(lca, S[top --]);
if(lca != S[top]) S[++ top] = lca;
break;
}
else E2.add(S[top], S[top - 1]), top --;
}
S[++ top] = a[i];
}
while(top > 1) E2.add(S[top], S[top - 1]), top --;
sum[1] = 0; DP(1, 0); DP2(1, 0);
for(int i = 1; i <= K; i ++) printf("%d ", ans[b[i]]), mark[b[i]] = 0, ans[b[i]] = 0;
puts("");
} void init()
{
bit[0] = 1; for(int i = 1; i <= 20; i ++) bit[i] = bit[i - 1] << 1;
Log[0] = -1; for(int i = 1; i < maxn * 2; i ++) Log[i] = Log[i >> 1] + 1;
} int main()
{
init(); n = read();
for(int i = 1; i < n; i ++)
{
int x = read(), y = read();
E1.add(x, y);
}
dfs(1, 0);
for(int i = 1; i <= Log[T]; i ++)
for(int j = 1; j + bit[i - 1] <= T; j ++)
ST[j][i] = min(ST[j][i - 1], ST[j + bit[i - 1]][i - 1]);
int q = read();
for(int i = 1; i <= q; i ++) Solve();
return 0;
}
【题解】HNOI2014世界树的更多相关文章
- [题解] [HNOI2014] 世界树
题面 [HNOI2014]世界树 题解 从数据范围很容易看出是个虚树DP(可惜看出来了也还是不会做) 虚树大家应该都会, 不会的话自己去搜吧, 我懒得讲了, 我们在这里只需要考虑如何DP即可 首先我们 ...
- [BZOJ3572][Hnoi2014]世界树
[BZOJ3572][Hnoi2014]世界树 试题描述 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条 ...
- 【BZOJ3572】[Hnoi2014]世界树 虚树
[BZOJ3572][Hnoi2014]世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森 ...
- bzoj3572[Hnoi2014] 世界树 虚树+dp+倍增
[Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1921 Solved: 1019[Submit][Status][Dis ...
- BZOJ 3572: [Hnoi2014]世界树
BZOJ 3572: [Hnoi2014]世界树 标签(空格分隔): OI-BZOJ OI-虚数 OI-树形dp OI-倍增 Time Limit: 20 Sec Memory Limit: 512 ...
- bzoj 3572: [Hnoi2014]世界树 虚树 && AC500
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 520 Solved: 300[Submit][Status] ...
- bzoj 3572 [Hnoi2014]世界树(虚树+DP)
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 645 Solved: 362[Submit][Status] ...
- <虚树+树型DP> HNOI2014世界树
<虚树+树型DP> HNOI2014世界树 #include <iostream> #include <cstdio> #include <cstring&g ...
- BZOJ3572:[HNOI2014]世界树——题解
+++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...
随机推荐
- 我错了的N个学习
其实在面对自己的失误的时候,勇敢的说我错了,就是我错了,不找借口,不找理由,然后就开始分析错误的原因,分析,总结,学习,提高,成为自己成长的垫脚石,这个才是正确的做法,做人要拿出精神头,拼死至休的劲头 ...
- Odd CSS syntax. [class^='icon-'], [class*=' icon-']
原文: https://stackoverflow.com/questions/20322740/odd-css-syntax-class-icon-class-icon I am going thr ...
- 「日常训练」Watering Flowers(Codeforces Round #340 Div.2 C)
题意与分析 (CodeForces 617C) 题意是这样的:一个花圃中有若干花和两个喷泉,你可以调节水的压力使得两个喷泉各自分别以\(r_1\)和\(r_2\)为最远距离向外喷水.你需要调整\(r_ ...
- 关于css,js显示不出来
有时候取消了对js,css文件的拦截,但是在网页上还是显示不了,可以试一下下面的方法: 在jsp页面添加下面内容 css的调用路径用path来代替
- Qt-QML-C++交互实现文件IO系统
QMl是没有自己的文件IO控制的,这里如果我们需要对文件进行读写操作,那么就需要去C++或者JS完成交互,交互方式有多种,由于我还没有掌握,这里就不介绍具体的交互方式了.这里就简单说明一下我的实现过程 ...
- 180602-nginx多域名配置
文章链接:https://liuyueyi.github.io/hexblog/2018/06/02/180602-nginx多域名配置/ nginx多域名配置 原来的域名过期了,重新买了一个hhui ...
- Linux命令应用大词典-第23章 进程和服务管理
23.1 ps:报告当前进程的快照 23.2 top:显示当前正在运行的进程 23.3 pgrep:按名称和其他属性查找进程 23.4 pidof:查找正在运行的进程的进程号 23.5 pstree: ...
- 小程序开发中,纯css实现内容收起折叠功能
不多说,直接上代码: wxml页面: <!--收起折叠 begin--> <view style='width:100%;background:#fff;border-top:1px ...
- Spring 3整合Quartz 2实现定时任务:动态添加任务
先展示一下后台管理定时任务效果图: 1.新增任务页面: 2.列表页(实现任务的禁用启用) 3.数据库脚本: -- ------------------------------ Table struct ...
- Samba共享权限分配
案例推荐:http://www.cnblogs.com/mchina/archive/2012/12/18/2816717.html 本文不详细介绍全部参数,只介绍完成需求的一些参数. 需求: 1,账 ...