P2633 Count on a tree

题意:

给定一棵 n 个节点的树,每个点有一个权值。有 m 个询问,每次给你 u,v,k,你需要回答 u xor last 和 v 这两个节点间第 k 小的点权。

其中last 是上一个询问的答案,定义其初始为 0,即第一个询问的 u 是明文。

题解:

很明显,主席树,而且强制在线(更是主席树)
主席树是维护了一个类似前缀和的数据结构,当要查询线性区间[l,r]的第k小时,用第r个线段树减第l-1个线段树,得到的就是[l,r]之间的权值线段树(因为主席树维护的就是前缀和),然后直接用二分查找第k小就行
在本题中给了一个树,问点u到点v之间的第k小,我们都知道树上差分(应该都知道),我们利用树上差分就可以得到u到v之间的数据
定义s[u]为从根节点到点u节点的主席树,那么u到v之间的所有数值信息的主席树就应该是:
s[u]+s[v]-s[lca[u,v]]-s[fa[lca(u,v)]]
因为需要lca所以要用到倍增,可以在dfs中插入每个点

代码:


#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define M 2000010
int read(){int ans=0,w=1;char c=getchar();while(c!='-'&&!isdigit(c))c=getchar();if(c=='-')w=-1,c=getchar();while(isdigit(c))ans=ans*10+c-'0',c=getchar();return ans*w;
}
int n,m,num,lastans=0,u,v,tot,cnt;
struct Edge{int v,next;}E[N<<1];
int head[N],a[N],b[N],fa[N][32],dep[N];
int rt[M]={0},ls[M]={0},rs[M]={0},siz[M]={0};
void add(int u,int v){E[++tot]=(Edge){v,head[u]};head[u]=tot;
}
void modify(int &rt,int lastrt,int l,int r,int val){rt=++cnt;ls[rt]=ls[lastrt]; rs[rt]=rs[lastrt];siz[rt]=siz[lastrt]+1;if(l==r)return;int mid=l+r>>1;if(mid>=val)modify(ls[rt],ls[lastrt],l,mid,val);else modify(rs[rt],rs[lastrt],mid+1,r,val);
}
int query(int rt1,int rt2,int rt3,int rt4,int l,int r,int k){if(l==r)return l;int mid=(l+r)>>1;int tmp=siz[ls[rt1]]+siz[ls[rt2]]-siz[ls[rt3]]-siz[ls[rt4]];if(tmp>=k)return query(ls[rt1],ls[rt2],ls[rt3],ls[rt4],l,mid,k);else return query(rs[rt1],rs[rt2],rs[rt3],rs[rt4],mid+1,r,k-tmp);
}
void dfs(int u,int f){dep[u]=dep[f]+1;for(int i=head[u];i;i=E[i].next){int v=E[i].v;if(v==fa[u][0])continue;fa[v][0]=u;modify(rt[v],rt[u],1,num,a[v]);dfs(v,u);}
}
int Lca(int x,int y){if(dep[x]<dep[y])swap(x,y);int t=dep[x]-dep[y];for(int i=0;(1<<i)<=t;i++)if((1<<i)&t)x=fa[x][i];for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];if(x==y)return x;return fa[x][0];
}
int main(){n=read();m=read();for(int i=1;i<=n;i++)b[i]=a[i]=read();sort(b+1,b+n+1);num=unique(b+1,b+n+1)-b;for(int i=1;i<n;i++){u=read();v=read();add(u,v);add(v,u);}for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b;modify(rt[1],rt[0],1,num,a[1]);dfs(1,0);int up=log2(n);for(int k=1;k<=up;k++)for(int i=1;i<=n;i++)fa[i][k]=fa[fa[i][k-1]][k-1];for(int i=1;i<=m;i++){u=read();v=read();int k=read();u^=lastans;int lca=Lca(u,v);int ans=b[query(rt[u],rt[v],rt[lca],rt[fa[lca][0]],1,num,k)];printf("%d\n",ans);lastans=ans;}return 0;
}

P2633 Count on a tree相关推荐

  1. 主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree...

    题面: Count on a tree 题解: 主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y) ...

  2. 洛谷P2633 Count on a tree

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  3. bzoj 2588 Spoj 10628. Count on a tree (可持久化线段树)

    Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB Submit: 7669  Solved: 1894 [Sub ...

  4. BZOJ2588 Count on a tree DFS序+LCA+值域主席树

    Count on a tree 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答 ...

  5. [SPOJ-COT]Count on a tree

    [SPOJ-COT]Count on a tree 题面 You are given a tree with N nodes. The tree nodes are numbered from 1 t ...

  6. BZOJ2588 Count on a tree 【树上主席树】

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB Submit: 7577  Solved: 185 ...

  7. 【SPOJ】Count On A Tree II(树上莫队)

    [SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...

  8. Count on a tree

    bzoj  2588: Spoj 10628. Count on a tree http://www.lydsy.com/JudgeOnline/problem.php?id=2588 Descrip ...

  9. BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树

    BZOJ 2588 Count on a tree 题面 求树上两点之间路径上第k大的点权. 题解 一开始看到这道题觉得是树剖,然后又听说是主席树,然后以为是主席树+树剖,差点没吓死-- 然后发现,如 ...

最新文章

  1. python程序代码大全-调试Python程序代码的几种方法总结
  2. kubernetes (1)基本概念
  3. Struts1.2配置详解
  4. require php 5.3.0,PHP 5.3.0 安装分析心得
  5. Android中土司(Toast)的使用
  6. Kafka核心源码解析 - KafkaController源码解析
  7. linux cp通同时新建目录_Linux 新手应该知道的 26 个命令
  8. spingMVC post 提交乱码问题
  9. 959. 由斜杠划分区域
  10. 联想17TV语音遥控教程 语音点播更方便
  11. Window+Anaconda3+TensorFlow少挖坑安装
  12. 锚点盒子随滚动条浮动
  13. 感觉最近有多个机器人给吾博客评论
  14. 容器技术Docker K8s 42 Serverless Kubernetes(ASK)详解-ASK应用管理
  15. cognos报表制作学习(一)cognos如何新建普通的reportstudio报表
  16. VMware12虚拟机怎么下载安装?保姆级安装教程,让你一分钟学会
  17. sphinxapi.php 详解,【转】Sphinx PHP api全文检索的例子
  18. 微信小程序:经典语录大全微信小程序源码
  19. 响铃:AWE2018只是“草船”,三星已成大屏电视“东风”
  20. [个人笔记] Zabbix配置钉钉群聊告警机制

热门文章

  1. TensorFlow的这些骚操作你都知道吗?
  2. 上班族吐槽大集合:那些发生在公司的傻X奇遇
  3. sql连接远程服务器索引超出了_手机怎么连接服务器远程桌面?RD client远程桌面使用教程...
  4. 6计算机系统的组成是,计算机系统的组成(范文)(6页)-原创力文档
  5. linux安装toncat环境变量,linux下JDK,tomcat的安装与环境变量配置
  6. yum java 1.7_centos通过yum安装jdk1.7或1.8
  7. pdf编辑软件adobe acrobat_分享一款PDF编辑和阅读软件Acrobat
  8. php 常用rpc框架,php的轻量级rpc框架yar
  9. 数据科学与python语言实验——NumPy数值计算基础
  10. linux find查找文件然后删除,linu查找find命令及删除7天前的文件