bzoj2588 Count on a tree
题意:给定一棵树,有点权,不带修改,询问路径点权第K大,强制在线。
这道题建主席树的方法好机智。按照BFS/DFS序建树,对于每个点,建出“这个点到根节点的路径上的点”组成的权值线段树,某个节点的树由父节点的树更改一条链得来。查询时用路径两个端点到根的线段树减去lca到根节点的线段树的2倍就得到了这条路径。注意lca的点权要特殊处理一下,不要把lca多减一次。据说只要分别减去lca和lca的父亲即可,查询的时候传4棵线段树的节点。
于是抖机灵强行传3个节点,单独处理lca,结果RE了一坨…..因为lca的权值小于区间中点的权值并不一定是lca处在[l,r]区间的左半部分,还有可能是lca在[l,r]区间的左边,加句rk[lca]>=l就过了.调了一小时,虚死….
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
int n,m;
struct edge{
int to,next;
}lst[maxn<<];int len=;
int first[maxn];
void addedge(int a,int b){
lst[len].to=b;
lst[len].next=first[a];
first[a]=len++;
}
int c[maxn];
int q[maxn];
int depth[maxn],p[maxn][];
void bfs(){
int head=,tail=;
depth[]=;
q[tail++]=;
int x;
while(head!=tail){
x=q[head++];
for(int pt=first[x];pt;pt=lst[pt].next){
if(lst[pt].to==p[x][])continue;
p[lst[pt].to][]=x;
depth[lst[pt].to]=depth[x]+;
q[tail++]=lst[pt].to;
}
for(int j=;p[x][j];++j)p[x][j+]=p[p[x][j]][j];
}
}
int LCA(int u,int v){
if(depth[u]<depth[v])swap(u,v);
for(int j=;j>=;--j){
if(depth[p[u][j]]>=depth[v])u=p[u][j];
}
if(u==v)return u;
for(int j=;j>=;--j){
if(p[u][j]!=p[v][j]){
u=p[u][j];v=p[v][j];
}
}
return p[u][];
}
struct node{
int sum;
node *lch,*rch;
node(){
lch=rch=;
sum=;
}
}t[maxn*];int cnt=;
int tot=;
node *root[maxn];
int qx;
int seq[maxn],dict[maxn],rk[maxn];
void Insert(node *rt1,node* &rt2,int l,int r){
++cnt;rt2=t+cnt;
if(l==r){
rt2->sum=rt1->sum+;
rt2->lch=rt2->rch=t+;
return;
}
int mid=(l+r)>>;
if(qx<=mid){
rt2->rch=rt1->rch;
Insert(rt1->lch,rt2->lch,l,mid);
}else{
rt2->lch=rt1->lch;
Insert(rt1->rch,rt2->rch,mid+,r);
}
rt2->sum=rt2->lch->sum+rt2->rch->sum;
}
void build_all(){
root[]=t+;
root[]->rch=root[]->lch=t+;
root[]->sum=;
for(int i=;i<n;++i){
qx=rk[q[i]];
Insert(root[p[q[i]][]],root[q[i]],,tot);
}
}
bool cmp(const int &x,const int &y){
return c[x]<c[y];
}
int lca;
int query(node *rt1,node *rt2,node *rt3,int l,int r){
if(l==r)return l;
int mid=(l+r)>>;
int lsum=rt1->lch->sum+rt2->lch->sum-*(rt3->lch->sum);
if(l<=rk[lca]&&rk[lca]<=mid)lsum++;
//if(rk[lca]<=mid) 错误的写法.这时rk[lca]可以小于l
if(qx<=lsum)return query(rt1->lch,rt2->lch,rt3->lch,l,mid);
else{
qx-=lsum;
return query(rt1->rch,rt2->rch,rt3->rch,mid+,r);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i){
scanf("%d",c+i);
seq[i]=i;
}
sort(seq+,seq+n+,cmp);
int old=c[seq[]]-;
for(int i=;i<=n;++i){
if(old!=c[seq[i]]){
old=c[seq[i]];++tot;
dict[tot]=c[seq[i]];
}
rk[seq[i]]=tot;
}
int a,b,k;
for(int i=;i<n;++i){
scanf("%d%d",&a,&b);
addedge(a,b);addedge(b,a);
}
bfs();
build_all();
int lastans=;
while(m--){
scanf("%d%d%d",&a,&b,&k);
a^=lastans;
qx=k;lca=LCA(a,b);
lastans=dict[query(root[a],root[b],root[lca],,tot)];
if(m)printf("%d\n",lastans);
else printf("%d",lastans);
}
return ;
}
bzoj2588 Count on a tree的更多相关文章
- 洛谷P2633/bzoj2588 Count on a tree (主席树)
洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...
- BZOJ2588 Count on a tree 【树上主席树】
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Submit: 7577 Solved: 185 ...
- 主席树+dfs SPOJ BZOJ2588 Count on a tree
这道题我由于智障错误导致一直错. 在树上建主席树,加上lca思想,很简单. #include<bits/stdc++.h> using namespace std; ; struct no ...
- [BZOJ2588]Count on a tree(LCA+主席树)
题面 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问 ...
- [bzoj2588][count on a tree] (主席树+lca)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 【填坑向】spoj COT/bzoj2588 Count on a tree
这题是学主席树的时候就想写的,,, 但是当时没写(懒) 现在来填坑 = =日常调半天lca(考虑以后背板) 主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分 ...
- BZOJ2588:Count on a tree(主席树)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- [Bzoj2588]Count on a tree(主席树+LCA)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- BZOJ2588 SPOJ10628 Count on a tree 【主席树】
BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ...
随机推荐
- eclipse/intellij idea 远程调试hadoop 2.6.0
很多hadoop初学者估计都我一样,由于没有足够的机器资源,只能在虚拟机里弄一个linux安装hadoop的伪分布,然后在host机上win7里使用eclipse或Intellj idea来写代码测试 ...
- Git开发备忘
1.在Git中,上传了中文命名的文件,但是后面想删除的时候,发现中文命名被转义了. 利用Git add是无法添加这类文件的,所以这里我们需要用到 git add -u命令,即可实现成功添加. 2.在G ...
- Openwrt Image Builder/SDK 初探
image builder和SDK既可以从官网上下载,又可以自己进行编译(make menuconfig).官网上下载的是预先帮你编译好的,这样可以大量节省自己编译源码花的时间,这两个东西相当于半成品 ...
- 工作随笔——Intellij_idea-14官方快捷键中文版
听说Intellij Idea好几年了.因为快捷键的原因,所以一直没有放弃eclipse.上周末抽了点时间,用google翻译+自己实践翻译了一下官方的快捷键. 基本做完的时候在百度文库上突然搜索到一 ...
- <实训|第十一天>学习一下linux中的进程,文件查找,文件压缩与IO重定向
[root@localhost~]#序言 在今后的工作中,运维工程师每天的例行事务就是使用free -m,top,uptime,df -h...每天都要检查一下服务器,看看是否出现异常.那么今天我们就 ...
- 知乎UWP 预览
又是很久都没有写博客了,为了表达歉意,奉上一个新的App,O(∩_∩)O! 因为商店的知乎太多了,然而,,所以一直打算自己动手写一个. 近段时间有些假期加上课程不是很忙,抽时间写了这个知乎.商店链接 ...
- socket.io简单说明及在线抽奖demo
socket.io简单说明及在线抽奖demo socket.io 简介 Socket.IO可以实现实时双向的基于事件的通信. 它适用于各种平台,浏览器或设备,也同样注重可靠性和速度. socket.i ...
- SqlServer导入数据到MySql
1.下载MySql ODBC Driver并进行安装.例如我下载的这个安装包是mysql-connector-odbc-5.1.6-win32.msi. 2.装完后,添加odbc数据源: 3.在sql ...
- 弱占优策略--Weakly Dominant Strategy
Weakly Dominant Strategy Equilibrium(均衡). 先说弱占优.一个策略弱占优就是说,无论其他人采取什么样的策略,这个策略的回报都大于等于其他策略的回报.如果所有人都使 ...
- struts 2.3.14.1 包详解
1.struts2-convention-plugin-2.3.14.1.jar: @ParentPackage(default-package) @Namespace("/") ...