【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 ...
随机推荐
- Elasticsearch.Net 异常:[match] query doesn't support multiple fields, found [field] and [query]
用Elasticsearch.Net检索数据,报异常: )); ElasticLowLevelClient client = new ElasticLowLevelClient(settings); ...
- 【BUG】12小时制和24小时制获取当天零点问题
[BUG]12小时制和24小时制获取当天零点问题 最近在写定时服务的时候,要获取当天的零点这个时间,但是是这样获取的 DateTime dt = DateTime.Parse(DateTime.Now ...
- html js div随鼠标移动
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- asp.net 设计条码code 11的问题
前一段时间思考了一些条码生成的问题,其实条码也可以说是加密的文件显示. 一个条码首先要有规定 比如code 11 又 1234567890 - 这11个字符组成 而1 又用 5码 表示 "1 ...
- java-sun.misc.BASE64Decode AccessException
在使用sun.misc中base64类时,eclipse可能会报找不到Access异常 只需要修改一下访问方式即可,如下: 右键项目->属性->Javabulid path->jre ...
- underscore.js源码解析(五)—— 完结篇
最近公司各种上线,所以回家略感疲惫就懒得写了,这次我准备把剩下的所有方法全部分析完,可能篇幅过长...那么废话不多说让我们进入正题. 没看过前几篇的可以猛戳这里: underscore.js源码解析( ...
- 20162316刘诚昊 第八周实验报告:实验二 Java面向对象程序设计
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.没有Linux基础的同学建议先学习<L ...
- Eclipse/myEclipse 代码提示/自动提示/自动完成设置(转)
一.设置超级自动提示 设置eclipse/myEclipse代码提示可以方便开发者,不用在记住拉杂的单词,只用打出首字母,就会出现提示菜单.如同dreamweaver一样方便. 1.菜单window- ...
- lintcode-463-整数排序
463-整数排序 给一组整数,按照升序排序,使用选择排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法. 样例 对于数组 [3, 2, 1, 4, 5], 排序后为:[1, 2, 3, 4, 5 ...
- DNS服务器的解析
---恢复内容开始--- DNS前言: 英特网作为域名和IP地址相互映射的一个分不式数据库,能够使用户更方便的访问互联网.而不用去记住能够被机器直接读取的IP地址的过程叫做域名解析(或主机名解析).D ...