题目

P5346 【XR-1】柯南家族

做法

聪明性是具有传递性的,且排列是固定的

那么先预处理出每个点的名次,用主席树维护\(k\)大值

一眼平衡树,遍历的同时插入\(O(log^2n)\),总时间复杂度\(O(nlog^2n)\)

显然还需要优化,考虑两个点的比较:按深度递减比较值,如果在等长前提下值相等,则比较深度最浅且的不一样的祖先的大小

这和后缀比较大小相似,我们后缀数组来实现排列的这个过程

Code

#include<bits/stdc++.h>
typedef int LL;
const LL maxn=1e6+9;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3)+(x<<1)+c-'0'; c=getchar();
}return x*f;
}
struct node{
LL to,nxt;
}dis[maxn];
LL n,num,q,m,tim;
LL head[maxn],fa[maxn],a[maxn],sa[maxn],x[maxn],y[maxn],z[maxn],c[maxn],rk[maxn],inc[maxn][25],b[maxn],dfn[maxn],low[maxn];
inline void Add(LL u,LL v){
dis[++num]=(node){v,head[u]}; head[u]=num;
}
inline void Sort(){
for(LL i=1;i<=n;++i) ++c[x[i]=a[i]];
for(LL i=2;i<=m;++i) c[i]+=c[i-1];
for(LL i=n;i>=1;--i) sa[c[x[i]]--]=i;
for(LL i=1;i<=n;++i) rk[sa[i]]=i;
for(LL len=1,t=0;len<n;len<<=1,++t){
LL num(0);
for(LL i=1;i<=n;++i) z[i]=rk[inc[i][t]];
for(LL i=0;i<=n;++i) c[i]=0;
for(LL i=1;i<=n;++i) ++c[z[i]]; for(LL i=1;i<=n;++i) c[i]+=c[i-1];
for(LL i=n;i>=1;--i) y[c[z[sa[i]]]--]=sa[i]; for(LL i=0;i<=m;++i) c[i]=0;
for(LL i=1;i<=n;++i) ++c[x[i]]; for(LL i=1;i<=m;++i) c[i]+=c[i-1];
for(LL i=n;i>=1;--i) sa[c[x[y[i]]]--]=y[i];
for(LL i=1;i<=n;++i) rk[sa[i]]=i;
std::swap(x,y);
x[sa[1]]=num=1;
for(LL i=2;i<=n;++i)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[inc[sa[i]][t]]==y[inc[sa[i-1]][t]])?num:++num;
if(num==n) break;
m=num;
}
}
struct Tree{
LL root[maxn],nod,size[maxn*10],son[maxn*10][2];
void Update(LL &now,LL pre,LL l,LL r,LL x){
now=++nod; size[now]=size[pre]+1;
if(l==r) return; LL mid(l+r>>1);
if(x<=mid){ Update(son[now][0],son[pre][0],l,mid,x); son[now][1]=son[pre][1]; }
else{ Update(son[now][1],son[pre][1],mid+1,r,x); son[now][0]=son[pre][0]; }
}
LL Query1(LL now,LL l,LL r,LL k){
if(l==r) return sa[l]; LL mid(l+r>>1);
LL ret(size[son[now][0]]);
return k<=ret?Query1(son[now][0],l,mid,k):Query1(son[now][1],mid+1,r,k-ret);
}
LL Query2(LL pre,LL now,LL l,LL r,LL k){
if(l==r) return sa[l]; LL mid(l+r>>1);
LL ret(size[son[now][0]]-size[son[pre][0]]);
return k<=ret?Query2(son[pre][0],son[now][0],l,mid,k):Query2(son[pre][1],son[now][1],mid+1,r,k-ret);
}
}T1,T2;
void Fir(LL u){
inc[u][0]=fa[u];
for(LL i=1;i<=20;++i){
inc[u][i]=inc[inc[u][i-1]][i-1]; if(!inc[u][i]) break;
}
for(LL i=head[u];i;i=dis[i].nxt) Fir(dis[i].to);
}
void Dfs(LL u){
dfn[u]=++tim;
T1.Update(T1.root[u],T1.root[fa[u]],1,n,rk[u]);
T2.Update(T2.root[tim],T2.root[tim-1],1,n,rk[u]);
for(LL i=head[u];i;i=dis[i].nxt) Dfs(dis[i].to);
low[u]=tim;
}
inline void Init(){
n=Read(); q=Read();
for(LL i=2;i<=n;++i) Add(fa[i]=Read(),i);
for(LL i=1;i<=n;++i) b[i]=a[i]=Read();
std::sort(b+1,b+1+n); m=std::unique(b+1,b+1+n)-b-1;
for(LL i=1;i<=n;++i) a[i]=std::lower_bound(b+1,b+1+m,a[i])-b;
}
int main(){
Init();
Fir(1);
Sort();
std::reverse(sa+1,sa+1+n);
for(LL i=1;i<=n;++i) rk[sa[i]]=i;
Dfs(1);
while(q--){
LL op(Read()),x(Read());
if(op==1) printf("%d\n",rk[x]);
else{
LL k(Read());
if(op==2) printf("%d\n",T1.Query1(T1.root[x],1,n,k));
else printf("%d\n",T2.Query2(T2.root[dfn[x]-1],T2.root[low[x]],1,n,k));
}
}
return 0;
}

P5346 【XR-1】柯南家族(后缀数组+主席树)的更多相关文章

  1. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  2. [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...

  3. LOJ_#2720. 「NOI2018」你的名字 _后缀数组+主席树+倍增

    题面: https://loj.ac/problem/2720 考虑枚举T串的每个后缀i,我们要做两件事. 一.统计有多少子串[i,j]在S中要求位置出现. 二.去重. 第二步好做,相当于在后缀数组上 ...

  4. BZOJ 5496: [2019省队联测]字符串问题 (后缀数组+主席树优化建图+拓扑排序)

    题意 略 分析 考场上写了暴力建图40分溜了-(结果只得了30分) 然后只要优化建边就行了 首先给出的支配关系无法优化,就直接A向它支配的B连边. 考虑B向以B作为前缀的所有A连边,做一遍后缀数组,两 ...

  5. HDU - 6704 K-th occurrence (后缀数组+主席树/后缀自动机+线段树合并+倍增)

    题意:给你一个长度为n的字符串和m组询问,每组询问给出l,r,k,求s[l,r]的第k次出现的左端点. 解法一: 求出后缀数组,按照排名建主席树,对于每组询问二分或倍增找出主席树上所对应的的左右端点, ...

  6. [2019CCPC网络赛][hdu6704]K-th occurrence(后缀数组&&主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6704 题意为查询子串s[l...r]第k次出现的位置. 写完博客后5分钟的更新 写完博客才发现这份代码 ...

  7. [HEOI2016] 字符串 - 后缀数组,主席树,ST表,二分

    [HEOI2016] 字符串 Description 给定一个字符串 \(S\), 有 \(m\) 个询问,每个询问给定参数 \((a,b,c,d)\) ,求 \(s[a..b]\) 的子串与 \(s ...

  8. HDU-6704 K-th occurrence(后缀数组+主席树)

    题意 给一个长度为n的字符串,Q次询问,每次询问\((l,r,k)\) , 回答子串\(s_ls_{l+1}\cdots s_r\) 第\(k\) 次出现的位置,若不存在输出-1.\(n\le 1e5 ...

  9. BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...

随机推荐

  1. 浅学CLR via C#笔记之类型转换

    我们都知道CLR最重要的一个特性就是类型安全,它在运行时就知道对象类型. 但我们会经常用到将一种类型转换成另一种类型,CLR也允许将对象转成他的实际类型,或者是它的基类型. 在C#中,支持隐士转换成它 ...

  2. axios配置及使用(发起请求时带上token)

    1.安装 利用npm安装 npm install axios --save 2.引入即可使用 import axios from 'axios' 3.目录 4.各个文件设置: (1)env.js ex ...

  3. pygame安装遇到的坑

    坑一:python版本冲突,电脑同时安装多个版本的python,由于每个都是python.exe,cmd命令窗口输入的python不一定是你想要的版本,所以最好还是安装单个版本即可. 坑二:由于电脑安 ...

  4. JavaScript中进制和字符编码问题

    1.进制: JavaScript中允许使用字面量的形式声明不同进制的数字: var a = 0b10; // 2 声明一个二进制 var b = 010; // 8 八进制,严格模式下会报错 var ...

  5. 【DRF框架】版本控制组件

    DRF框架提供的版本控制组件 核心代码:           version, scheme = self.determine_version(request, *args, **kwargs)req ...

  6. 每日一题-——LeetCode(78)子集

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集).输入: nums = [1,2,3]输出:[ [3],  [1],  [2],  [1,2,3],  [1,3],  [2, ...

  7. Nginx虚拟主机配置--配置Nginx的主配置文件

    单台Nginx WEB服务器同时会配置N个网站,也可称之为配置N个虚拟域名的主机,即多个域名对应同一个80端 口. 每个虚拟主机可以是一个独立网站.可以具有独立域名,同一台物理机上面的虚拟主机相互之间 ...

  8. 22 Jquery 事件

    一.概述: 当用户与浏览器进行交互时这些方法被用于注册行为生效, 并进一步处理这些注册行为. 二.绑定事件处理器 .bind() ..unbind():为一个元素绑定一个事件处理程序.3.0版本已经弃 ...

  9. Linux下干净卸载mysql

    1.首先查看mysql的安装情况 rpm -qa|grep -i mysql 显示之前安装了: MySQL-client-5.5.25a-1.rhel5 MySQL-server-5.5.25a-1. ...

  10. postgresql sql查询结果添加序号列与每组第一个序号应用

    1.postgresql 查询每组第一个 ROW_NUMBER () OVER (partition by 字段 ORDER BY  字段  DESC) 写法:SELECT  ROW_NUMBER ( ...