【BZOJ2588】Spoj 10628. Count on a tree

Description

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

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

M行,表示每个询问的答案。

Sample Input

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
0 5 2
10 5 3
11 5 4
110 8 2

Sample Output

2
8
9
105
7

HINT

N,M<=100000
暴力自重。。。

题解:先树剖求出LCA,然后再树上搞一个主席树,第i棵线段树保存的是从根到i的路径上的所有点,然后查询的时候就在用a的线段树+b的线段树-lca(a,b)的线段树-fa(lca(a,b))的线段树就行了。

主席树写的还是不熟练,注意在建树的时候一定要按着DFS序建。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
struct NUM
{
int num,org;
}v[maxn];
struct NODE
{
int siz,ls,rs;
}s[maxn*40];
int n,m,tot,nm,ans,cnt;
int ref[maxn],root[maxn],q[maxn];
int fa[maxn],size[maxn],top[maxn],son[maxn],deep[maxn],to[maxn<<1],next[maxn<<1],head[maxn];
bool cmp1(NUM a,NUM b)
{
return a.num<b.num;
}
bool cmp2(NUM a,NUM b)
{
return a.org<b.org;
}
void add(int a,int b)
{
to[cnt]=b;
next[cnt]=head[a];
head[a]=cnt++;
}
void dfs1(int x)
{
size[x]=1;
for(int i=head[x];i!=-1;i=next[i])
{
if(to[i]!=fa[x])
{
fa[to[i]]=x,deep[to[i]]=deep[x]+1;
dfs1(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]]) son[x]=to[i];
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
q[++q[0]]=x;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=next[i])
if(to[i]!=fa[x]&&to[i]!=son[x])
dfs2(to[i],to[i]);
}
void insert(int x,int &y,int l,int r,int p)
{
y=++tot;
if(l==r)
{
s[y].siz=s[x].siz+1;
return ;
}
int mid=l+r>>1;
if(p<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,p);
else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,p);
s[y].siz=s[s[y].ls].siz+s[s[y].rs].siz;
}
void query(int a,int b,int c,int d,int l,int r,int p)
{
if(l==r)
{
ans=ref[l];
return ;
}
int mid=l+r>>1;
if(s[s[a].ls].siz+s[s[b].ls].siz-s[s[c].ls].siz-s[s[d].ls].siz>=p) query(s[a].ls,s[b].ls,s[c].ls,s[d].ls,l,mid,p);
else query(s[a].rs,s[b].rs,s[c].rs,s[d].rs,mid+1,r,p-s[s[a].ls].siz-s[s[b].ls].siz+s[s[c].ls].siz+s[s[d].ls].siz);
}
int getlca(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]>deep[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
}
if(deep[x]<deep[y]) return x;
return y;
}
int readin()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=readin(),m=readin();
memset(head,-1,sizeof(head));
int i,a,b,c,d,e;
for(i=1;i<=n;i++) v[i].num=readin(),v[i].org=i;
sort(v+1,v+n+1,cmp1);
ref[nm]=-1;
for(i=1;i<=n;i++)
{
if(v[i].num>ref[nm]) ref[++nm]=v[i].num;
v[i].num=nm;
}
sort(v+1,v+n+1,cmp2);
for(i=1;i<n;i++)
{
a=readin(),b=readin();
add(a,b),add(b,a);
}
deep[1]=1,dfs1(1),dfs2(1,1);
for(i=1;i<=n;i++) insert(root[fa[q[i]]],root[q[i]],1,nm,v[q[i]].num);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&e);
a^=ans;
int c=getlca(a,b),d=fa[c];
query(root[a],root[b],root[c],root[d],1,nm,e);
printf("%d",ans);
if(i!=m) printf("\n");
}
return 0;
}

【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA的更多相关文章

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

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

  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. spoj COT - Count on a tree(主席树 +lca,树上第K大)

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

  4. spoj cot: Count on a tree 主席树

    10628. Count on a tree Problem code: COT You are given a tree with N nodes.The tree nodes are number ...

  5. 【主席树】bzoj2588 Spoj 10628. Count on a tree

    每个点的主席树的root是从其父转移来的.询问的时候用U+V-LCA-FA(LCA)即可. #include<cstdio> #include<algorithm> using ...

  6. BZOJ2588: Spoj 10628. Count on a tree

    传送门 刚开始看错题以为是dfs序瞎搞.. 后来看清题了开始想用树剖瞎搞... 感觉要滚粗啊.. 对于每个点到根的路径建立线段树,暴力建MLE没跑,上主席树,然后$(x,y)$的路径就可以先求出来$L ...

  7. 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  ...

  8. [bzoj2588][count on a tree] (主席树+lca)

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

  9. bzoj2588: Spoj 10628. Count on a tree(树上第k大)(主席树)

    每个节点继承父节点的树,则答案为query(root[x]+root[y]-root[lca(x,y)]-root[fa[lca(x,y)]]) #include<iostream> #i ...

随机推荐

  1. vmware克隆Centos6.4虚拟机网卡无法启动问题

    vmware克隆Centos6.4虚拟机网卡无法启动问题                 2014-02-26 16:44:54 标签:老男孩培训 vmware克隆问题 网卡无法启动          ...

  2. VS2010在C#头文件中添加文件注释的方法(转)

    步骤: 1.VS2010 中找到(安装盘符以D盘为例)D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTempl ...

  3. mysql修改密码与password字段不存在mysqladmin connect to server at localhost failed

    mysqladmin: connect to server at 'localhost' failed 停止mysql服务 systemctl stop mysql 安全模式启动 chown -R m ...

  4. 防止短连接耗尽你的动态TCP端口

    详见TCP协议https://en.wikipedia.org/wiki/Transmission_Control_Protocol但是TIME_WAIT是有时间窗口的,Linux默认是60秒.所以如 ...

  5. e553. 作为浏览器访问URL

    // See also e551 精简的Applet try { URL url = new URL(getDocumentBase(), "http://hostname.com/page ...

  6. web开发之微信公众号---微信公众好开发

    --------------------------------------time:2015/11/5 ----------------------------------------------- ...

  7. erlang工具:Sublime Text的插件

    SublimErl  :https://github.com/ostinelli/SublimErl   (推荐,操作较简单)                                      ...

  8. 如何研究某个gene的ceRNA 网络

    研究人员针对 PTEN 这个关键的抑癌基因,来探究调控该基因表达的ceRNA 网络: 分析策略: 1)预测能调控该基因的miRNAs 通过miRanda 软件预测和实验验证相结合的方式,挑选出 miR ...

  9. Fastqc 能够识别的碱基编码格式

    Fastqc 能够自动识别序列的碱基编码格式,我查看一下源代码,发现是碱基编码格式一共分为 1)sanger/illumina 1.9 2) illumina 1.3 3) illumina 1.5 ...

  10. 基于bootstrap的select(可多选)

    如图: