10628. Count on a tree

Problem code: COT

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 NOI前的最后一道题编这道主席树的题算是了解了对于主席树的“恐惧“。
这道题的大致思路是对于树上每一个点,都在其父节点基础上建主席树。
第一次编没有初始化建树操作的线段树来优化内存。还算比较顺利。以后看题的时候注意对于没有指明范围的量离散化。
虽然参加不了NOI现场赛,但还是希望自己在同步赛中rp++
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 211000
#define MAXE 211000
#define MAXT 16001000
int n,m;
int ptr[MAXN];
struct Edge
{
int np;
Edge *next;
}E[MAXE],*V[MAXN];
int tope=-;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
}
int wei[MAXN];
int depth[MAXN];
int fa[MAXN];
void dfs(int now,int d)
{
Edge *ne;
depth[now]=d;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==fa[now])continue;
fa[ne->np]=now;
dfs(ne->np,d+);
}
}
int jump[MAXN][];
void init_lca()
{
int i,j;
for (i=;i<=n;i++)
{
jump[i][]=fa[i];
}
for (j=;j<;j++)
{
for (i=;i<=n;i++)
{
jump[i][j]=jump[jump[i][j-]][j-];
}
}
}
void swim(int &now,int d)
{
int i=;
while (d)
{
if (d&)now=jump[now][i];
i++;
d>>=;
}
}
int lca(int x,int y)
{
if (depth[x]<depth[y])
{
swim(y,depth[y]-depth[x]);
}
if (depth[y]<depth[x])
{
swim(x,depth[x]-depth[y]);
}
if (x==y)return x;
int i;
for (i=;i>=;i--)
{
if (jump[x][i]!=jump[y][i])
{
x=jump[x][i];
y=jump[y][i];
}
}
return fa[x];
}
struct node
{
int lch,rch,sum;
}tree[MAXT];
int topt=;
int get_node(node *nd)
{
if (nd==NULL)
{
return ++topt;
}
topt++;
tree[topt]=*nd;
return topt;
}
/*void build_tree(int &now,int l,int r)
{
now=++topt;
// tree[now].l=l;
// tree[now].r=r;
if (l==r)return ;
int mid=(l+r)/2;
build_tree(tree[now].lch,l,mid);
build_tree(tree[now].rch,mid+1,r);
}*/
void add_val(int &now,int &base,int l,int r,int pos,int v)
{
now=get_node(&tree[base]);
tree[now].sum+=v;
if (l==pos&&r==pos)
{
return ;
}
int mid=(l+r)/;
if (pos<=mid)
{
add_val(tree[now].lch,tree[base].lch,l,mid,pos,v);
return ;
}
if (mid<pos)
{
add_val(tree[now].rch,tree[base].rch,mid+,r,pos,v);
return ;
}
}
int root[MAXN];
void dfs2(int now)
{
Edge *ne;
add_val(root[now],root[fa[now]],,m,wei[now],);
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==fa[now])continue;
dfs2(ne->np);
}
}
struct weight_t
{
int id,w;
}wei2[MAXN];
bool cmp_w(const weight_t &w1,const weight_t &w2)
{
return w1.w<w2.w;
}
bool cmp_id(const weight_t &w1,const weight_t &w2)
{
return w1.id<w2.id;
}
int main()
{
//freopen("input.txt","r",stdin);
int i,j,k,x,y,z;
int q;
m=;
scanf("%d%d",&n,&q);
for (i=;i<=n;i++)
{
scanf("%d",&wei2[i].w);
wei2[i].id=i;
}
sort(&wei2[],&wei2[n+],cmp_w);
x=;y=-;
for (i=;i<=n;i++)
{
if (wei2[i].w!=y)
{
y=wei2[i].w;
ptr[x+]=wei2[i].w;
wei2[i].w=++x;
}else wei2[i].w=x;
}
sort(&wei2[],&wei2[n+],cmp_id);
for (i=;i<=n;i++)
wei[i]=wei2[i].w;
for (i=;i<n-;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
Edge *ne;
dfs(,);
init_lca();
//build_tree(root[0],1,m);
add_val(root[],root[],,m,wei[],);
for (ne=V[];ne;ne=ne->next)
dfs2(ne->np);
int t,temp;
int a[],topa;
int ans;
int l,r,mid;
for (i=;i<q;i++)
{
scanf("%d%d%d",&x,&y,&z);
t=lca(x,y);
if (t!=)a[]=root[fa[t]];
else a[]=;
a[]=root[t];
a[]=root[x];
a[]=root[y];
ans=;
l=,r=m;
while (true)
{
mid=(l+r)/;
temp=ans;
if (l==r)break;
if (a[])ans-=tree[tree[a[]].lch].sum;
if (a[])ans-=tree[tree[a[]].lch].sum;
if (a[])ans+=tree[tree[a[]].lch].sum;
if (a[])ans+=tree[tree[a[]].lch].sum;
if (ans>=z)
{
if (a[])a[]=tree[a[]].lch;
if (a[])a[]=tree[a[]].lch;
if (a[])a[]=tree[a[]].lch;
if (a[])a[]=tree[a[]].lch;
r=mid;
ans=temp;
}else
{
if (a[])a[]=tree[a[]].rch;
if (a[])a[]=tree[a[]].rch;
if (a[])a[]=tree[a[]].rch;
if (a[])a[]=tree[a[]].rch;
l=mid+;
}
}
printf("%d\n",ptr[l]);
}
}

spoj cot: Count on a tree 主席树的更多相关文章

  1. spoj COT - Count on a tree(主席树 +lca,树上第K大)

    您将获得一个包含N个节点的树.树节点的编号从1到Ñ.每个节点都有一个整数权重. 我们会要求您执行以下操作: uvk:询问从节点u到节点v的路径上的第k个最小权重 输入 在第一行中有两个整数Ñ和中号.( ...

  2. Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588 2588: Spoj 10628. Count on a tree Time Limit ...

  3. 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA

    [BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...

  4. BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

    分析:树上第k小,然后我想说的是主席树并不局限于线性表 详细分析请看http://www.cnblogs.com/rausen/p/4006116.html,讲的很好, 然后因为这个熟悉了主席树,真是 ...

  5. SP10628 COT - Count on a tree 主席树

    Code: #include<cstdio> #include<cstring> #include<algorithm> #include<string> ...

  6. SPOJ Count on a tree(主席树+LCA)

    一.题目 COT - Count on a tree You are given a tree with N nodes. The tree nodes are numbered from 1 to  ...

  7. SPOJ - COT Count on a tree

    地址:http://www.spoj.com/problems/COT/en/ 题目: COT - Count on a tree #tree You are given a tree with N  ...

  8. 【BZOJ-2588】Count on a tree 主席树 + 倍增

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[ ...

  9. Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)

    题目链接:https://www.spoj.com/problems/COT/en/ 题目: 题意: 给你一棵有n个节点的树,求节点u到节点v这条链上的第k大. 思路: 我们首先用dfs进行建题目给的 ...

随机推荐

  1. 项目中发现的一些关于JavaScript中JSON的注意点

    一个是怎样创建JSON: var obj = {}; obj['name'] = value; obj['anotherName'] = anotherValue; 假设要创建多级的JSON,则: i ...

  2. 【PHP分享】Windows tail工具分享

    作者:zhanhailiang 日期:2014-09-28 在Linux下能够使用tail -f工具实时查看输出的日志.近期切换到本地Windows开发环境,顿时有点不爽.百度了下,最终找到tail的 ...

  3. careercup-链表 2.4

    2.4 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前. 思路:将小于的结点还是保存在原来的链表中,将大于等于x的结点加入一个新的链表,最后将这两个链表链接起 ...

  4. Flume NG中的ElasticSearch Sink

    ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apach ...

  5. iOS中Git的使用

    打开终端: 查看Git的版本的终端命令:git —version 输入:ssh 查看是否已经存在ssh. 如果存在,先将已有的ssh备份,或者将新建的ssh生成到另外的目录下 如果不存在,通过默认的参 ...

  6. OC协议

    概念:定义了一个接口,其他类负责来实现这些接口.如果你的类实现了一个协议的方法时,则说该类遵循此协议. 非正式协议:非正式协议虽名为协议,但实际上是挂于NSObject上的未实现分类(Unimplem ...

  7. Android开发之UI更新交互机制与实例解析

    android开发过程中,经常需要更新UI的状态和文案等.这是就需要对UI进行 更新.在android中更新UI一般有三种方法,handler机制.RunOnUiThread方法以及AsyncTask ...

  8. .net缓存应用与分析

    在 ASP.NET 提供的许多特性中,相比 ASP.NET 的所有其他特性,缓存对应用程序的性能具有最大的潜在影响,利用缓存和其他机制,ASP.NET 开发人员可以接受使用开销很大的控件(例如,Dat ...

  9. Amazon S3 上传文件 SSL23_GET_SERVER_HELLO握手错误

    题外话:今天偶尔来逛逛,发现我真是懒到家了.居然有半年前的留言我都没有来看过,真对不起留言的同学,希望他的问题已经解决了. 这两三天一直被亚马逊S3上传文件的问题困扰着,直到昨天晚上终于搞定了,工作群 ...

  10. Parallel类(简化Task 操作)

    Parallel类 Parallel类是对线程的一个很好抽象.该类位于System.Threading.Tasks命名空间中,提供了数据和任务并行性. 1.用Parallel.For()方法循环 // ...