题意:一个n个点的数, m个人住在其中的某些点上, 每个人的标号1-m, 询问u-v 路径上标号前a个人,并输出标号,a < 10。

作法, 利用倍增, ID[j][i] 表示i到i的第2^j个祖先上前10个人, 那么每次询问直接维护就好了,细节好多, 刚开始不知道怎么求ID[j][i]。

这里把2^j分成两部分, 前2^(j-1)和 后2^(j-1)个, 然后递推的维护。

感觉树链剖分也可以做, 不知道会不会TLE, 树链剖分的话 线段树的每个点维护10个值, 每次合并就行了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + ;
const int maxdep = ;
int par[maxdep][maxn], dep[maxn], n;
vector <int> ID[maxdep][maxn], cit[maxn];
vector <int> G[maxn];
void init() {
for (int i = ; i < maxn; i++) {
G[i].clear();
cit[i].clear();
for (int j = ; j < maxdep; j++) {
ID[j][i].clear();
}
}
memset(par, -, sizeof (par));
}
void update(vector <int> &v1, vector <int> &v2) {
for (int x: v2) {
v1.push_back(x);
}
sort (v1.begin(), v1.end());
v1.erase(unique(v1.begin(), v1.end()), v1.end());
while (v1.size() > ) {
v1.pop_back();
}
}
void dfs(int u, int father) {
par[][u] = father;
dep[u] = dep[father] + ;
for (int i = u; i <= u; i++) {
update(ID[][i], cit[par[][i]]);
update(ID[][i], cit[i]);
for (int j = ; j + < maxdep; j++) {
if (~par[j][i]) {
par[j+][i] = par[j][par[j][i]];
update(ID[j+][i], cit[i]);
update(ID[j+][i], ID[j][i]);
update(ID[j+][i], ID[j][par[j][i]]);
} else {
par[j+][i] = -;
}
}
}
for (int v: G[u]) {
if (v != father) {
dfs(v, u);
}
} }
int lca(int u, int v) {
if (dep[u] > dep[v]) {
swap(u, v);
}
for (int k = ; k < maxdep; k++) {
if ((dep[v] - dep[u]) >> k & ) {
v = par[k][v];
}
}
if (u == v) {
return u;
}
for (int i = maxdep-; i >= ; i--) {
if (par[i][u] != par[i][v]) {
u = par[i][u];
v = par[i][v];
}
}
return par[][u];
}
int anc;
vector <int> solve(int u, int v) {
vector <int> res;
if (u == v) {
update(res, cit[u]);
}
for (int i = maxdep-; i >= ; i--) {
if (~par[i][u] && dep[par[i][u]] >= dep[anc]) {
update(res, ID[i][u]);
u = par[i][u];
}
}
for (int i = maxdep-; i >= ; i--) {
if (~par[i][v] && dep[par[i][v]] >= dep[anc]) {
update(res, ID[i][v]);
v = par[i][v];
}
}
vector<int> emp;
update(res, emp);
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int m, q;
while (~scanf ("%d%d%d", &n, &m, &q)) {
init();
for (int i = ; i < n-; i++) {
int u, v;
scanf ("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for (int i = ; i < m; i++) {
int c;
scanf ("%d", &c);
if (cit[c].size() < ) {
cit[c].push_back(i+);
ID[][c].push_back(i+);
}
}
dfs(, );
while(q--) {
int u, v, a;
scanf ("%d%d%d", &u, &v, &a);
anc = lca(u, v);
auto res = solve(u, v);
int tot = min((int)res.size(), a);
printf("%d%c", tot, " \n"[!tot]);
for (int i = ; i < min((int)res.size(), a); i++) {
printf("%d%c", res[i], " \n"[i+==min((int)res.size(), a)]);
}
}
}
return ;
}

Codeforces Round #326 (Div. 1) - C. Duff in the Army 树上倍增算法的更多相关文章

  1. Codeforces Round #326 Div.1 C.Duff in the Army 树上倍增

    题意概述: 给出一棵N个结点的树,然后有M个居民分散在这棵树的结点上(允许某个结点没有居民).现在给出一些询问形如u,v,a,定义k=min(x,a),其中x表示的是u->v路径上的居民数量.将 ...

  2. Codeforces Round #326 (Div. 2) D. Duff in Beach dp

    D. Duff in Beach Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/588/probl ...

  3. Codeforces Round #326 (Div. 2) C. Duff and Weight Lifting 水题

    C. Duff and Weight Lifting Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  4. Codeforces Round #326 (Div. 2) B. Duff in Love 分解质因数

    B. Duff in Love Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/588/proble ...

  5. Codeforces Round #326 (Div. 2) A. Duff and Meat 水题

    A. Duff and Meat Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/588/probl ...

  6. Codeforces Round #326 (Div. 2) B Duff in Love 简单数论 姿势涨

    B. Duff in Love time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  7. Codeforces Round #381 (Div. 2) D. Alyona and a tree 树上二分+前缀和思想

    题目链接: http://codeforces.com/contest/740/problem/D D. Alyona and a tree time limit per test2 secondsm ...

  8. 【LCA】CodeForce #326 Div.2 E:Duff in the Army

    C. Duff in the Army Recently Duff has been a soldier in the army. Malek is her commander. Their coun ...

  9. Codeforces Round #326 (Div. 2) B. Pasha and Phone C. Duff and Weight Lifting

    B. Pasha and PhonePasha has recently bought a new phone jPager and started adding his friends' phone ...

随机推荐

  1. [原创] Fragment的添加、移除问题

    安卓一直在进化,Fragment就是个好东西,如果早5年做安卓开发,真要麻烦的多. 关于Fragment的讲解,这里很详尽: Android Fragment 真正的完全解析(上) Android F ...

  2. javascript DOM小结

    一:定义 dom:文档对象模型. dom是针对HTML和XML文档的一个API.dom描绘了一个层次化的节点树,允许开发人员添加.移除.修改页面的某一部分. 1:childNodes(返回当前节点的子 ...

  3. Javascript的AMD规范

    Javascript发展到今天,已经从一个小丑语言变成了不可替代的前端利器,已经脱离了低端的玩笑脚步,而转变为有规可依的强大语言. 本文主要讲述下如今被大力推广的AMD规范,为什么要AMD,什么场景是 ...

  4. 【转】jQuery教程

    “jQuery风暴” 推荐及配套代码下载 ziqiu.zhang 2011-03-24 00:28 阅读:15339 评论:100   从零开始学习jQuery(剧场版) 你必须知道的javascri ...

  5. 【vc】6_菜 单

    1.菜单命令响应函数: 提示:MFC都是采用大写字母来标识资源ID号的:为了区分资源类型,一般遵循这样一个原则:在“ID”字符串后加上一个标识资源类型的字母.例:菜单资源(Menu):ID_Mxxx: ...

  6. 【BZOJ2809】【splay启发式合并】dispatching

    Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级. ...

  7. 【转载】【挖掘Treap的潜力】

    原帖: http://fanhq666.blog.163.com/blog/static/819434262011021105212299/ 你的Treap能支持以下操作吗?1.区间增减 2.区间求最 ...

  8. js创建对象的三种方法:文本标识法和构造器函数法和返回对象的函数

    文本标识法和定义变量差不多,像这样 var obj = {name:'HanMM','2':'Dali'}; 函数构造器法  先创建一个对象函数 function Obj() { this.addre ...

  9. WF学习笔记(一)

    -流程启动方式1: WorkflowInvoker.Invoke(new Workflow1()); -流程启动方式2: WorkflowApplication instance = new Work ...

  10. 在winform中调用js文件并输出结果

    在winform中调用js文件并输出结果默认分类 2007-10-19 16:35:06 阅读25 评论0 字号:大中小 由于项目需要在winform中调一个强大的js,所以把这个tip记录在此: 1 ...