题目传送门(内部题66)


输入格式

第一行,一个正整数$n$,一个自然数$q$,一个整数$type$。
第二行,$n$个正整数,代表$a_i$。
接下来$n-1$行,每行两个正整数$u$、$v$,代表树中存在一条边$(u,v)$。
接下来$q$行,每行两个正整数$r$、$k$,然后$k$个正整数$x_1,x_2,...,x_k$。询问中的$p_i=(x_i−1+lastans\times type)\mod n+1$。$lastans$为上一个询问的答案,一开始$lastans=0$。


输出格式

输出$q$行,每行一个自然数,代表对应询问的答案。


输出格式

输出$q$行,每行一个自然数,代表对应询问的答案。


样例

样例输入:

5 7 0
1 2 3 4 5
1 2
2 3
2 4
1 5
1 2 4 5
2 2 4 5
3 2 4 5
4 2 4 5
5 2 4 5
5 1 2
100 3 1 2 5

样例输出:

0
0
1
0
0
3
95


数据范围与提示

保证$type\in \{0,1\},1\leqslant a_i,r\leqslant 10^9,u,v,x_i\in [1,n]$。


题解

可以说是一道树上主席树的板子题(然而当时并不会……)。

显然集合$S$就是所有$p_k$到所有$p_k$的$LCA$之间的所有点。

与普通主席树的区别在于,普通主席树维护的是序列,树上主席树维护的是从当前节点到根节点的这条链。

提取出一段类似树上差分的思想。

时间复杂度:$\Theta(\sum k\log \sum k)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[2000001];
int head[1000001],cnt;
int n,q,type;
int a[1000001];
int que[1000001];
int ans;
int fa[1000001][21],depth[1000001];
int root[20000000],tr[20000000],lson[20000000],rson[20000000],tot;
void add(int x,int y)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
void insert(int &x,int pre,int l,int r,int w)
{
x=++tot;
tr[x]=tr[pre]+1;
lson[x]=lson[pre];
rson[x]=rson[pre];
if(l==r)return;
int mid=(l+r)>>1;
if(w<=mid)insert(lson[x],lson[pre],l,mid,w);
else insert(rson[x],rson[pre],mid+1,r,w);
}
int askmax(int x,int pre,int l,int r,int L,int R)
{
if(tr[x]==tr[pre])return 0;
if(l==r)return l;
int mid=(l+r)>>1;
int res=0;
if(mid<R)res=askmax(rson[x],rson[pre],mid+1,r,L,R);
if(res)return res;
if(L<=mid)res=askmax(lson[x],lson[pre],l,mid,L,R);
if(res)return res;
return 0;
}
int askmin(int x,int pre,int l,int r,int L,int R)
{
if(tr[x]==tr[pre])return 0;
if(l==r)return l;
int mid=(l+r)>>1;
int res=0;
if(L<=mid)res=askmin(lson[x],lson[pre],l,mid,L,R);
if(res)return res;
if(mid<R)res=askmin(rson[x],rson[pre],mid+1,r,L,R);
if(res)return res;
return 0;
}
void pre_dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
{
if(depth[e[i].to])continue;
depth[e[i].to]=depth[x]+1;
insert(root[e[i].to],root[x],1,1e9,a[e[i].to]);
fa[e[i].to][0]=x;
for(int j=1;j<=20;j++)
fa[e[i].to][j]=fa[fa[e[i].to][j-1]][j-1];
pre_dfs(e[i].to);
}
}
int LCA(int x,int y)
{
if(depth[x]>depth[y])swap(x,y);
for(int i=20;i>=0;i--)
if(depth[fa[y][i]]>=depth[x])
y=fa[y][i];
if(x==y)return x;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
int main()
{
scanf("%d%d%d",&n,&q,&type);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
insert(root[1],0,1,1e9,a[1]);
depth[1]=1;
pre_dfs(1);
while(q--)
{
int r,k;
scanf("%d%d",&r,&k);
que[0]=0;
for(int i=1;i<=k;i++)
{
int x;scanf("%d",&x);
que[++que[0]]=(x-1+ans*type)%n+1;
}
ans=0x3f3f3f3f;
int lca=que[1];
for(int i=2;i<=k;i++)
lca=LCA(lca,que[i]);
for(int i=1;i<=k;i++)
{
int w1=askmax(root[que[i]],root[fa[lca][0]],1,1e9,1,r);
int w2=askmin(root[que[i]],root[fa[lca][0]],1,1e9,r,1e9);
if(w1&&w2)ans=min(ans,min(r-w1,w2-r));
else if(w1)ans=min(ans,r-w1);
else if(w2)ans=min(ans,w2-r);
}
printf("%d\n",ans);
}
return 0;
}

rp++

[CSP-S模拟测试]:e(树上主席树)的更多相关文章

  1. [CSP-S模拟测试]:序列(主席树)

    题目描述 小$A$把自己之前得到的序列展示给了小$B$,不过这一次,他并不要求小$B$模仿他之前的行为.他给了小$B$一些询问,每个询问都是$l\ r\ x$的形式,要求小$B$数出在序列的第$l$个 ...

  2. SPOJ COT Count on a tree(树上主席树 + LCA 求点第k小)题解

    题意:n个点的树,每个点有权值,问你u~v路径第k小的点的权值是? 思路: 树上主席树就是每个点建一棵权值线段树,具体看JQ博客,LCA用倍增logn求出,具体原理看这里 树上主席树我每个点的存的是点 ...

  3. p3302 [SDOI2013]森林(树上主席树+启发式合并)

    对着题目yy了一天加上看了一中午题解,终于搞明白了我太弱了 连边就是合并线段树,把小的集合合并到大的上,可以保证规模至少增加一半,复杂度可以是\(O(logn)\) 合并的时候暴力dfs修改倍增数组和 ...

  4. 【洛谷2633】Count on a tree(树上主席树)

    点此看题面 大致题意: 给你一棵树,每次问你两点之间第\(k\)小的点权,强制在线. 主席树 这种题目强制在线一般就是数据结构了. 而看到区间第\(k\)小,很容易就能想到主席树. 至少不会有人想到树 ...

  5. Count on a tree 树上主席树

    Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...

  6. bzoj3123 [Sdoi2013]森林 树上主席树+启发式合并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3123 题解 如果是静态的查询操作,那么就是直接树上主席树的板子. 但是我们现在有了一个连接两棵 ...

  7. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  8. ☆ [洛谷P2633] Count on a tree 「树上主席树」

    题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...

  9. [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)

    传送门 突然发现好像没有那么难……https://blog.csdn.net/stone41123/article/details/78167288 首先有两个操作,一个查询,一个连接 查询的话,直接 ...

随机推荐

  1. 红帽学习笔记[RHCSA] 第一周

    目录 红帽学习笔记[RHCSA] 环境 第一课 关于Shell 命令的基础知识 在终端中敲命令的快捷键 本次课程涉及的命令 第二课 常用的目录结构与用途 本次课程涉及到的命令 第三课 关于Linux的 ...

  2. [转帖]Oracle 使用sqlnet.ora/trigger限制/允许某IP或IP段访问指定用户

    Oracle 使用sqlnet.ora/trigger限制/允许某IP或IP段访问指定用户 原创 Oracle 作者:maohaiqing0304 时间:2016-05-03 17:05:46  17 ...

  3. MySQL-快速入门(1)基本数据库、表操作语句

    1.创建数据库 create database db_name;show create database db_name\G; //查看数据创建语句show databases; //查看当前创建的数 ...

  4. java基础笔记)(5)

    xml文件:树形存储格式:通过相同的xml文件实现不同的软件.不同的操作系统.不同的平台之间的信息通讯: 声明xml文件: <?xml version="1.0" encod ...

  5. PY个树状数组

    树状数组看起来比较简单,于是就挑它下手了... 于是生活终于也对咱下手了... 要讲的就两个东西,一个是开数组,全局变量写最前面,数组是这么开的: f=[0 for i in range(500005 ...

  6. Xdex(百度版)脱壳工具基本原理

    [原创]Xdex(百度版)脱壳工具基本原理作 者: sherrydl时 间: 2015-12-13,10:52:45链 接: http://bbs.pediy.com/showthread.php?t ...

  7. Cookie&Session笔记

    # 今日内容     1. 会话技术         1. Cookie         2. Session     2. JSP:入门学习 ## 会话技术     1. 会话:一次会话中包含多次请 ...

  8. [七月挑选]IntelliJ IDEA常用设置

    title: IntelliJ IDEA常用设置 设置idea的类注释快捷键 File -> Settings -> Live Templates 1.右边的 + -> Templa ...

  9. Mybatis驼峰式命名

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...

  10. [转载]MAC、IP头、TCP头、UDP头帧格式、详解

    原文地址:MAC.IP头.TCP头.UDP头帧格式.详解作者:iTudu 转自:http://zoufengfu168.blog.163.com/blog/static/546105520099133 ...