http://www.spoj.com/problems/COT/

(速度很快,排到了rank6)

这题让我明白了人生T_T

我知道我为什么那么sb了。

调试一早上都在想人生。

唉。

太弱。

太弱。

手一抖,真的一生就毁了。

不到一小时打好的代码,硬是调试了2小时。

这什么水平。

到头来,和network那题的错误一样,都是很逗的地方,上次漏打id,这次漏打root。

调了一早上,无限吐槽一早上。差点让我以为自己人生没戏了。

吐槽完毕。

这题做法可以用树剖做,但是太麻烦。

我是看了别人用主席树加lca做,速度很快,所以要来学习,并且还要为network那题的第二种做法打下基础,所以来写这题。

我们dfs后,可以发现,每一个点到lca(不包括lca)都是在一个连续的区间,所以我们用主席树来维护每个点的到根的形态,用dfs序来维护。

然后查找他们的路径u v就是查找 u到树根的主席树 和v到树根的主席树 和lca到树根的主席树 他们比k小的数量。然后做法和普通主席树一样。只不过 s=s(lson[u])+s(lson[v])-2*s(lson[lca]),如果lca本身在区间[l, m]内,s还要加上1,这个自己去领悟,我倒是领悟了一段时间的。

坑爹的属性我在代码里标记了,一定要铭记,千万以后不要犯这种sb错!!!!!

FIGHT!!!!!!!!!!!!!!!!!!!!!!!!!!!

(代码其实很短的,lca我用tarjan做,离线)

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define MID (l+r)>>1
#define dbg(x) cout << #x << " = " << x << endl
#define read(x) x=getint()
#define rdm(x) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { char c=getchar(); int k=1, ret=0; for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) ret=ret*10+c-'0'; return ret*k; }
const int N=100005;
struct ed { int to, next; } e[N<<1];
struct ND { int l, r, s; } t[N*20];
int ihead[N], cnt, num, lca[N], fa[N], p[N], a[N], b[N], k[N], id[N], root[N], u[N], v[N], n, m, ff;
bool vis[N];
vector<pair<int, int> > q[N];
inline void add(const int &u, const int &v) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;
e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u;
}
void update(const int &l, const int &r, int &pos) {
t[++num]=t[pos]; pos=num; ++t[pos].s;
if(l==r) return;
int m=MID;
if(ff<=m) update(l, m, t[pos].l); else update(m+1, r, t[pos].r);
}
int ifind(const int &x) { return x==p[x]?x:p[x]=ifind(p[x]); }
void dfs(const int &x) {
p[x]=x; root[x]=root[fa[x]]; ff=b[x]; update(1, n, root[x]);
rdm(x) if(e[i].to!=fa[x]) { fa[e[i].to]=x; dfs(e[i].to); p[e[i].to]=x; }
vis[x]=1;
int t=q[x].size();
for(int i=0; i<t; ++i) if(vis[q[x][i].first]) lca[q[x][i].second]=ifind(q[x][i].first);
}
int getans(const int &l, const int &r, const int &x, const int &y, const int &f, const int &key) {
if(l==r) return l;
int m=MID, s=t[t[x].l].s + t[t[y].l].s - (t[t[f].l].s << 1);
if(b[ff]>=l && b[ff]<=m) ++s; //这里要注意,lca是减掉了的,所以还要判断合法性
if(key<=s) return getans(l, m, t[x].l, t[y].l, t[f].l, key);
else return getans(m+1, r, t[x].r, t[y].r, t[f].r, key-s);
}
bool cmp(const int &x, const int &y) { return a[x]<a[y]; }
int main() {
read(n); read(m);
for(int i=1; i<=n; ++i) read(a[i]), id[i]=i;
sort(id+1, id+1+n, cmp);
for(int i=1; i<=n; ++i) b[id[i]]=i;
for(int i=1; i<n; ++i) add(getint(), getint());
for(int i=1; i<=m; ++i) {
read(u[i]); read(v[i]); read(k[i]);
q[u[i]].push_back(pair<int, int> (v[i], i));
q[v[i]].push_back(pair<int, int> (u[i], i));
}
dfs(1);
for(int i=1; i<=m; ++i) {
if(u[i]==v[i]) { printf("%d\n", a[u[i]]); continue; }
ff=lca[i];
printf("%d\n", a[id[getans(1, n, root[u[i]], root[v[i]], root[ff], k[i])]]); //被root[ff]坑了一早上,写成了ff。唉
}
return 0;
}

You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight.

We will ask you to perform the following operation:

  • u v k : ask for the kth minimum weight on the path from node u to node v

Input

In the first line there are two integers N and M.(N,M<=100000)

In the second line there are N integers.The ith integer denotes the weight of the ith node.

In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).

In the next M lines,each line contains three integers u v k,which means an operation asking for the kth minimum weight on the path from node u to node v.

Output

For each operation,print its result.

Example

Input:
8 5
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2 
Output:
2
8
9
105
7

【SPOJ】10628. Count on a tree(lca+主席树+dfs序)的更多相关文章

  1. BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...

  2. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  3. bzoj 2588 Spoj 10628. Count on a tree(主席树)

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  4. bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】

    算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分 #include<iostream> #include<cstdio> ...

  5. 【bzoj2588】Spoj 10628. Count on a tree 离散化+主席树

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  6. 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

    [BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...

  7. BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

    BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with ...

  8. [BZOJ2588]Count on a tree(LCA+主席树)

    题面 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问 ...

  9. 【bzoj2588/P2633】count on a tree —— LCA + 主席树

    (以下是luogu题面) 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问 ...

随机推荐

  1. win7/ubuntu双系统下,如何恢复成win7引导及卸载ubuntu

    电脑原来是win7系统,后来通过硬盘安装了Ubuntu,同时把Ubuntu设置成了开机引导项(开机时选择操作系统的界面成了紫色背景白色字体的界面),ubuntu引导开机的缺点是将来要卸载Ubuntu时 ...

  2. 用Matplotlib绘制二维图像

    唠叨几句: 近期在做数据分析,需要对数据做可视化处理,也就是画图,一般是用Matlib来做,但Matlib安装文件太大,不太想直接用它,据说其代码运行效率也很低,在网上看到可以先用Java做数据处理, ...

  3. PHP中magic_quotes_gpc动态关闭无效的问题

    昨天浏览线上项目,发现了一个问题:部分文本输出中的引号前多了一道反斜杠,比如: 引号内容多了\"反斜杠\" 单从页面展现的结果来看,猜测应该是PHP中的magic_quotes_g ...

  4. 【OpenStack】OpenStack系列3之Swift详解

    Swift安装部署(与keystone依赖包有冲突,需要安装不同版本eventlet) 参考:http://www.server110.com/openstack/201402/6662.html h ...

  5. Mybatis 动态sql标签

    1.动态SQL片段 通过SQL片段达到代码复用         <!-- 动态条件分页查询 -->          <sql id="sql_count"> ...

  6. 【leetcode】Binary Search Tree Iterator

    Binary Search Tree Iterator Implement an iterator over a binary search tree (BST). Your iterator wil ...

  7. JavaScript关闭窗口的同时打开新页面的方法

    做网页的时候需要弹出一个小窗口,然后要实现一个功能就是鼠标点击超链接关闭小窗口并打开一个新页面,就如同下图: 这是一个小窗口,点击超链接这个窗口会关闭并且会正常在浏览器打开新页面,首先写js关闭窗口的 ...

  8. libavcodec/dxva2.h:40:5: error: unknown type name 'IDirectXVideoDecoder'

    gcc 4.9.2 编译 ffmpeg-git-1aeb88b 是出现如下错误 > FFmpeg fails to make with: > > CC libavcodec/dxva ...

  9. hdu 1879 继续畅通工程 解题报告

    题目链接:http://code.hdu.edu.cn/showproblem.php?pid=1879 这条题目我的做法与解决Constructing Roads的解法是相同的. 0 表示没有连通: ...

  10. java\c程序的内存分配

    JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该 ...