SPOJ - COT 路径构造主席树
题意:给出一个带权树,多次询问路径\((u,v)\)的第k小权值
这是主席树往区间扩展到树上的套路题
由于是按路径查询,我们无法使用dfs序,但可利用主席树对父亲扩展的方法构造出链
因此要用dfs构造才能保证正确性
查询就xjb差分一下 \(u+v-lca-p_{lca}\)
注意p的父亲是自身的情况的特判
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
//#include<unordered_map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)a)
#define println(a) printf("%lld\n",(ll)a)
using namespace std;
const int MAXN = 2e5+11;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
ll n,m,nn,a[MAXN],b[MAXN],c[MAXN];
int dep[MAXN],p[MAXN][21],dfn[MAXN],pre[MAXN],dfned[MAXN],CLOCK;
map<ll,ll> mp;
void init(){
memset(head,-1,sizeof head);
tot=CLOCK=0;
}
void add(int u,int v){
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
}
void dfs(int u,int fa,int d){
dep[u]=d; //dfn[u]=++CLOCK;pre[CLOCK]=u;
rep(j,0,20){
if(u==1) p[u][j]=u;
else if(!j) p[u][j]=fa;
else p[u][j]=p[p[u][j-1]][j-1];
}
erep(i,u){
int v=to[i];
if(v==fa) continue;
dfs(v,u,d+1);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
rep(i,0,20){
if((dep[u]-dep[v])>>i&1){
u=p[u][i];
}
}
if(u==v) return u;
rrep(i,20,0){
if(p[u][i]!=p[v][i]){
u=p[u][i];
v=p[v][i];
}
}
return p[u][0];
}
struct FST{
int lc[MAXN<<5],rc[MAXN<<5];
int cnt[MAXN<<5];
int T[MAXN],tot;
void init(){tot=0;}
int build(int l,int r){
int cur=++tot;
lc[cur]=rc[cur]=cnt[cur]=0;
if(l==r) return cur;
int mid=l+r>>1;
lc[cur]=build(l,mid);
rc[cur]=build(mid+1,r);
return cur;
}
inline void copy(int cur,int old){
lc[cur]=lc[old];
rc[cur]=rc[old];
cnt[cur]=cnt[old];
}
int update(int old,int l,int r,int k,int v){
int cur=++tot;
copy(cur,old);
cnt[cur]+=v;
if(l==r) return cur;
int mid=l+r>>1;
if(k<=mid) lc[cur]=update(lc[old],l,mid,k,v);
else rc[cur]=update(rc[old],mid+1,r,k,v);
return cur;
}
int query(int T1,int T2,int T3,int T4,int l,int r,int k){
while(1){
if(l==r) return l;
int t=cnt[lc[T1]]+cnt[lc[T2]]-cnt[lc[T3]]-cnt[lc[T4]];
if(k<=t){
T1=lc[T1];
T2=lc[T2];
T3=lc[T3];
T4=lc[T4];
r=l+r>>1;
}else{
k-=t;
T1=rc[T1];
T2=rc[T2];
T3=rc[T3];
T4=rc[T4];
l=l+r>>1;l++;
}
}
}
}fst;
void fstbuild(int u,int fa){
if(u==1) fst.T[u]=fst.update(fst.T[0],1,nn,c[1],1);
else fst.T[u]=fst.update(fst.T[fa],1,nn,c[u],1);
erep(i,u){
int v=to[i];
if(v==fa) continue;
fstbuild(v,u);
}
}
int main(){
while(cin>>n>>m){
init(); mp.clear();
rep(i,1,n) b[i]=a[i]=read();
sort(b+1,b+1+n);
nn=unique(b+1,b+1+n)-b-1;
rep(i,1,n) c[i]=lower_bound(b+1,b+1+nn,a[i])-b;
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
add(v,u);
}
dfs(1,-1,1);
fst.init(); fst.T[0]=fst.build(1,nn);
//rep(i,1,n) fst.T[i]=fst.update(fst.T[i-1],1,CLOCK,a[pre[i]],1);
//fst.T[1]=fst.update(fst.T[0],1,nn,c[1],1);
//rep(i,2,n) fst.T[i]=fst.update(fst.T[p[i][0]],1,nn,c[i],1);
fstbuild(1,-1);
rep(i,1,m){
int u=read();
int v=read();
int k=read();
int anc=lca(u,v);
println(b[fst.query(fst.T[u],fst.T[v],fst.T[anc],fst.T[p[anc][0]==anc?0:p[anc][0]],1,nn,k)]);
}
}
return 0;
}
SPOJ - COT 路径构造主席树的更多相关文章
- SPOJ DQUERY D-query(主席树)
题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...
- SPOJ DQUERY D-query(主席树 区间不同数个数)
题意:问你区间有几个不同的数 思路:主席树nb.我们知道主席树每一个root都存着一棵权值线段树,现在我们在每个root中存位置,也就是01表示这个位置存不存在.然后我们用一个fa[a[i]]表示a[ ...
- SPOJ 3267. D-query (主席树,查询区间有多少个不相同的数)
3267. D-query Problem code: DQUERY English Vietnamese Given a sequence of n numbers a1, a2, ..., an ...
- 2018.08.04 spoj TTM to the moon(主席树)
spoj传送门 vjudge传送门 主席树板子题. 支持历史版本的区间和,区间和,区间修改和时光倒流. 其中新奇一点的也只有区间修改了,这个东西直接标记永久化就行了. 如果想下传标记的话也行,需要在p ...
- acm 2015北京网络赛 F Couple Trees 树链剖分+主席树
Couple Trees Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/problemset/problem/123 ...
- 莫队或权值线段树 或主席树 p4137
题目描述 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入格式 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l,r. 输出格式 ...
- spoj COT - Count on a tree (树上第K小 LCA+主席树)
链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们 ...
- Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)
题目链接:https://www.spoj.com/problems/COT/en/ 题目: 题意: 给你一棵有n个节点的树,求节点u到节点v这条链上的第k大. 思路: 我们首先用dfs进行建题目给的 ...
- 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 ...
随机推荐
- 洛谷 P1103 书本整理(动规)
洛谷 P1103 书本整理 题目描述 Frank是一个非常喜爱整洁的人.他有一大堆书和一个书架,想要把书放在书架上.书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架上.但是Frank发 ...
- 使用python把图片存入数据库-乾颐堂
一般情况下我们是把图片存储在文件系统中,而只在数据库中存储文件路径的,但是有时候也会有特殊的需求:把图片二进制存入数据库. 今天我们采用的是python+mysql的方式 MYSQL 是支持把图片存入 ...
- WireShark抓包的pcap文件格式分析
http://www.360doc.com/content/14/0220/11/15257968_354157537.shtml http://www.360doc.com/content/14/0 ...
- Mac OS X Yosemite & Arduino安装CH340 USB转串口驱动
新买的Arduino开发板 USB转串口使用了CH340芯片,在Mac OS X Yosemite上正常安装驱动后,在Arduino IDE的端口没发现相应的设备,使用以下方法后就能使用USB转串口调 ...
- 从源代码分析DbSet如何通过ObjectStateManager管理entity lifecycle的生命周期
一:Savechange的时候,怎么知道哪些entity被add,modify,delete,unchange ???? 如何来辨别... 在entity中打上标记来做表示...已经被跟踪了...当每 ...
- mybatis--mapper配置总结
mapper介绍 mapper使用规则:按业务划分,一个业务模块相关的sql均定义在一个mapper文件 mapper的xml格式: doctype: <!DOCTYPE mapper PUBL ...
- SOLR企业搜索平台 三 (schema.xml配置和solrj的使用)
标签:solrj 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://3961409.blog.51cto.com/3951409/8 ...
- c#设计模式之:外观模式(Facade)
一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...
- django media配置
当我们需要向服务器发送图片或视频,需要对这些媒体文件进行保存时,需要指定保存在哪并将保存的路径添加到路由中. 1.设置settings.py MEDIA_URL = '/media/' MEDIA_R ...
- luogu1357花园(矩阵运算)(状压DP)
不得不说本蒻做这个题目的时候内心是很蒙蔽的qwq 推了规律找错了结果还没有暴力的分数高qwq...... 开数组\(f[i][j]\)来记录前i个花圃,(这里运用到状压的思想)其中最近的m个的状态(二 ...