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 ...
随机推荐
- Cordova - 使用Cordova开发iOS应用实战5(获取手机里照片,并编辑)
使用Cordova可以很方便的通过js代码读取系统相簿里面的照片,同使用设备摄像头拍照一样,同样需要先添加camera插件. 一,添加camera插件 首先我们要在“终端”中进入工程所在的目录,然后运 ...
- 航空货运:运价类别Rate Class
1.普通货物运价(1)基础运价(代号N -注:Normal的首字母)民航总局统一规定各航段货物基础运价为45公斤以下普通货物运价.(2)重量分界点运价(代号Q -注:Quantity的首字母)国内航 ...
- Java并发编程实战(使用synchronized实现同步方法)
本文介绍java最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问,如果一个对象已用synchronized关键字声明,那么只有一个执行线程允许去访问它,其它试图访问这个对 ...
- Laravel 安装多国语言包后,phpstorm 还是报错
问题: 解决办法: vagrant@homestead:~/Code/awbeci$ composer require "overtrue/laravel-lang:~3.0" 总 ...
- C# 7.0 新特性1: 基于Tuple的“多”返回值方法
本文基于Roslyn项目中的Issue:#347 展开讨论. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: ...
- HTTP 状态代码表示什么意思?
HTTP 状态代码表示什么意思? 如果某项请求发送到您的服务器要求显示您网站上的某个网页,服务器将会返回 HTTP 状态码响应请求.此状态代码提供关于请求状态的信息,一些常见的状态代码为: 200 - ...
- 误人子弟的网络,谈谈HTTP协议中的短轮询、长轮询、长连接和短连接
引言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码.在研究一个项目的时候,源码里面用到了HTTP的长轮询.由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HT ...
- 用nhibernate的几点小经验
最近几个月都在用nhibernate做项目.写几点经验. 1. 解决Transient object exception 原项目是用Entity Framework做的.现在是用nhibernate代 ...
- VS2013 未找到与約束ContractName
vs2013打开项目无法加载项目,关闭时提示 未找到与約束ContractName... 解決方法,打開控制面板,找到下面這個程序 右击,选 择 修 复
- LaTeX常用数学符号表示方法
转自:http://www.mohu.org/info/symbols/symbols.htm 常用数学符号的 LaTeX 表示方法 (以下内容主要摘自“一份不太简短的 LATEX2e 介绍”) 1. ...