【bzoj2588】Count on a tree
Solution
不行我一定要来挂这道题qwq很气愤qwq(其实还不是因为自己蠢。。)
额首先说一下正解
如果这个问题放在序列上面的话。。直接离散化一下然后一个可持久化权值线段树就好了
然后放在树上的话,我们可以考虑处理树上点对问题的一个很常见的套路:
\]
那所以我们还是用可持久化权值线段树,每一个节点\(x\)从\(fa[x]\)更新过来就好了
一个小trick是在查询的时候直接传参这样比较方便
还有就是因为是点值,所以要记得算上\(lca\)处的值
好的然而我在场上想到的是这样的:
“放在序列上直接可持久化权值线段树那放在树上当然是套个树链剖分啊”
然后码了个线段树合并什么的qwq总共4k,然后T掉了,原因是。。貌似这题的合并还是怎么的并不是log的。。。
综上,这题一定要挂上来,太气了qwq被自己蠢哭我需要智力康复qwq
正解的代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define TOP 20
using namespace std;
const int N=100010,SEG=(N+20)*20;
struct xxx{
int y,nxt;
}a[N*2];
int pre[TOP+1][N],dep[N],V[N],val[N],Lis[N];
int h[N],sz[N],son[N];
int n,m,lastans,tot,dfn_t;
namespace Seg{/*{{{*/
int ch[SEG][2],sz[SEG],rt[N];
int n,tot,tot1;
void pushup(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]];}
int newnode(int pre){
ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1]; sz[tot]=sz[pre];
return tot;
}
void _insert(int pre,int &x,int d,int lx,int rx){
x=newnode(pre);
if (lx==rx){++sz[x]; return;}
int mid=lx+rx>>1;
if (d<=mid) _insert(ch[pre][0],ch[x][0],d,lx,mid);
else _insert(ch[pre][1],ch[x][1],d,mid+1,rx);
pushup(x);
}
void insert(int pre,int x,int d){_insert(rt[pre],rt[x],d,1,n);tot1=tot;}
int _query(int l,int r,int lca,int lx,int rx,int k,int pos){//pos=val[lca]
if (lx==rx) return lx;
int mid=lx+rx>>1,lsz=sz[ch[r][0]]+sz[ch[l][0]]-2*sz[ch[lca][0]];
if (lx<=pos&&pos<=mid) ++lsz;
if (k<=lsz) return _query(ch[l][0],ch[r][0],ch[lca][0],lx,mid,k,pos);
return _query(ch[l][1],ch[r][1],ch[lca][1],mid+1,rx,k-lsz,pos);
}
int query(int l,int r,int lca,int k){return _query(rt[l],rt[r],rt[lca],1,n,k,val[lca]);}
void _debug(int x,int l,int r){
if (!x){
for (int i=l;i<=r;++i) printf("%d %d\n",i,0);
return;
}
if (l==r) {printf("%d %d\n",l,sz[x]);return;}
int mid=l+r>>1;
_debug(ch[x][0],l,mid);
_debug(ch[x][1],mid+1,r);
}
void debug(int x){_debug(rt[x],1,n);}
}/*}}}*/
void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
void dfs(int fa,int x,int d){
pre[0][x]=fa; dep[x]=d;
Seg::insert(fa,x,val[x]);
for (int i=1;i<=TOP;++i) pre[i][x]=pre[i-1][pre[i-1][x]];
int u;
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa) continue;
dfs(x,u,d+1);
}
}
void prework(){
sort(Lis+1,Lis+1+n);
Lis[0]=unique(Lis+1,Lis+1+n)-Lis-1;
int x;
for (int i=1;i<=n;++i){
x=lower_bound(Lis+1,Lis+1+Lis[0],val[i])-Lis;
V[x]=val[i];
val[i]=x;
}
Seg::n=Lis[0];
}
int get_lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
for (int i=TOP;i>=0;--i)
if (dep[pre[i][x]]>=dep[y]) x=pre[i][x];
if (x==y) return x;
for (int i=TOP;i>=0;--i)
if (pre[i][x]!=pre[i][y]) x=pre[i][x],y=pre[i][y];
return pre[0][x];
}
void solve(int x,int y,int k){
int lca=get_lca(x,y);
/*Seg::debug(x); printf("\n");
Seg::debug(y); printf("\n");
Seg::debug(lca); printf("\n");*/
lastans=Seg::query(x,y,lca,k);
printf("%d\n",V[lastans]);
lastans=V[lastans];
}
int main(){/*{{{*/
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y,k;
scanf("%d%d",&n,&m);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<=n;++i) scanf("%d",val+i),Lis[++Lis[0]]=val[i];
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
prework();
dfs(0,1,1);
lastans=0;
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&k);
x^=lastans;
solve(x,y,k);
}
}/*}}}*/
【bzoj2588】Count on a tree的更多相关文章
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- 【BZOJ-2588】Count on a tree 主席树 + 倍增
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 3749 Solved: 873[ ...
- 【bzoj2588】Count on a tree 主席树
这题给人开了个新思路. 原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间. 此题若带修改怎么办? 若对某个点的权值做修改,则这个点的子树都会受影响,想 ...
- 【BZOJ2588】Count on a tree 题解(主席树+LCA)
前言:其实就是主席树板子啦……只不过变成了树上的查询 -------------------------- 题目链接 题目大意:求树上$u$到$v$路径第$k$大数. 查询静态区间第$k$大肯定是用主 ...
- 【SPOJ】Count On A Tree II(树上莫队)
[SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...
- 主席树+LCA【p2633 (bzoj2588】 Count on a tree
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 【BZOJ2558】Count on a tree
又是因为傻逼错误浪费了半天时间 原题: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个 ...
- 【SPOJ10628】Count on a tree
题目大意:给定一棵 N 个节点的树,点有点权,要求回答 M 个询问,每次询问点 u 到点 v 的简单路径(链)上权值第 K 小是多少. 题解:学习到了树上主席树. 主席树维护序列时,每次将后一个点的树 ...
- 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA
[BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...
随机推荐
- Swoole实现h5版聊天室笔记
声明:该聊天室目前只有一对多,一对一的聊天功能,另外,因为没有使用到mysql,所以还存在比较多的缺陷地方,但知道原理就差不多了,这里主要分享下swoole简易的聊天室制作思路. 开发环境:cento ...
- ConcurrentHashMap(JDK1.8)为什么要放弃Segment
今天看到一篇博客:jdk1.8的HashMap和ConcurrentHashMap,我想起了前段时间面试的一个问题:ConcurrentHashMap(JDK1.8)为什么要使用synchronize ...
- Python基础灬异常
异常&异常处理 异常!=错误 在程序运行过程中,总会遇到各种各样的错误. 有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的 ...
- hadoop之mapper类妙用
1. Mapper类 首先 Mapper类有四个方法: (1) protected void setup(Context context) (2) Protected void map(KEYIN k ...
- Blockchain For Dummies(IBM Limited Edition
Blockchain For Dummies(IBM Limited Edition)笔记 该系列内容主要介绍用于商业的区块链,有人说区块链之于贸易,犹如因特网之于信息.在商业领域区块链可以用于交易任 ...
- 第七次作业PSP
psp 进度条 代码累积折线图 博文累积折线图 psp饼状图
- Beta阶段第一次网络会议
Beta阶段第一次网络会议 游戏问题 游戏细节特征不够明显,大小虽然随着电脑分辨率的不同变化着,但是存在清楚的问题 游戏中的提示信息不够,玩家无法快速了解游戏 游戏中背景声音过于单一 游戏AI太简单 ...
- "群英队"电梯演讲
视频如下: https://imgcache.qq.com/tencentvideo_v1/playerv3/TPout.swf?max_age=86400&v=20161117&vi ...
- 在原有的基础之上,启用NAT模型
# 给虚拟主机实例添加一个网关 route add default gw 192.168.23.1 # 在宿主机打开网卡间转发功能 echo 1 > /proc/sys/net/ipv4/i ...
- 【Linux 命令】- more和less
more命令 more功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上. more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b ...