【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 ...
随机推荐
- Qt 将字符串转成16进制显示
最近项目用到了需要将字符串转换成16进制显示.这玩意折腾了一上午. 首先,数据块内容 struct UserData { char Head[3] = {'X','J','J'}; char Flag ...
- Python接口测试实战4(上) - 接口测试框架实战
如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...
- Python中abs()和math.fabs()区别
描述:Python中fabs(x)方法返回x的绝对值.虽然类似于abs()函数,但是两个函数之间存在以下差异: abs()是一个内置函数,而fabs()在math模块中定义的. fabs()函数只适用 ...
- axios封装(二)队列管理
在某些特定的场景(比如 即时搜索 ,表格分页),会频繁的发起ajax请求,而由于ajax是异步API,所以返回的时序并不能够保证,这时候就需要实现一个ajax队列,在相同的请求发起时,取消处理上一个请 ...
- mnist手写数字识别(Logistic回归)
import numpy as np from sklearn.neural_network import MLPClassifier from sklearn.linear_model import ...
- SICP读书笔记 1.3
SICP CONCLUSION 让我们举起杯,祝福那些将他们的思想镶嵌在重重括号之间的Lisp程序员 ! 祝我能够突破层层代码,找到住在里计算机的神灵! 目录 1. 构造过程抽象 2. 构造数据抽象 ...
- 【python 3.6】python读取json数据存入MySQL(一)
整体思路: 1,读取json文件 2,将数据格式化为dict,取出key,创建数据库表头 3,取出dict的value,组装成sql语句,循环执行 4,执行SQL语句 #python 3.6 # -* ...
- R之RMySQL
linux,mysql和R的版本信息: Linux naci 3.19.0-16-generic #16-Ubuntu SMP Server version: 5.6.24-0ubuntu2 (Ubu ...
- Amazon - removed your selling privileges and placed a temporary hold on any funds - 1
Hello, We are writing to let you know that we have removed your selling privileges and placed a temp ...
- 关于css文字的扩展
1.不换行: .title{ white-space:nowrap; text-overflow:ellipsis; } 2.超出变三点 .title{ white-space:nowrap; tex ...