您的位置:首页 > 其它

BZOJ 10628 Luogu 2633

2018-01-09 20:08 134 查看
BZOJ 10628 Luogu2633——count on a tree

题意:查询一定区间内第K小的点权。

由于有lastans所以强制在线,这道题就相当于树上的主席树,

树链剖分+主席树,主席树相比普通主席树有一丢丢的改变,

root[i]不再是指向root[i-1],而是指向它在树上的父亲,

维护的序列是它到根节点的这条路径。

所以在求区间第k小时,可以用前缀和的思想加上lca,

val[u]+val[v]-val[lca]-val[fa[lca]],

得出的是lca分别到u和v的这两条路径中每个节点的数出现的次数。

然后用二分思想,跟普通主席树一样,二分直至l==r。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int size[100005]={0},fa[100005]={0},son[100005]={0},top[100005],dep[100005]={0},ls[100005*20],rs[100005*20],val[100005*20],root[100005],sz,v[100005],
head[100005*2]={0},t=0,a[100002]={0},tot=0,real[100005]={0},dfn[100005]={0},num,cnt=0,pai[100005];
struct hh
{int  u,v,next;
}e[200005];
void add(int x,int  y)
{
t++;
e[t].u=x;
e[t].v=y;
e[t].next=head[x];
head[x]=t;
}
void dfs(int now,int anc)
{

int i;
top[now]=anc;
tot++;
dfn[now]=tot;
real[tot]=now;
if(son[now]==-1) return;
dfs(son[now],anc);
for(i=head[now];i!=0;i=e[i].next)
{
int v=e[i].v;
if(v!=fa[now]&&v!=son[now])
dfs(v,v);
}
}
void build(int u)
{
size[u]=1;
for(int i=head[u];i!=0;i=e[i].next)
{
int v=e[i].v;
if(v!=fa[u])
{
dep[v]=dep[u]+1;
fa[v]=u;
build(v);
size[u]=size[u]+size[v];
if(son[u]==-1||size[v]>size[son[u]])
son[u]=v;
}
}
}
int getlca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
swap(x,y);
}
x=fa[top[x]];
}
if(dep[x]<dep[y])
{
swap(x,y);
}
return y;
}
void insert(int &p,int cmp,int x,int l,int r){
p=++cnt;ls[p]=ls[cmp];rs[p]=rs[cmp];val[p]=val[cmp]+1;
if(l!=r){
int mid=(l+r)/2;
if(x<=mid){
insert(ls[p],ls[cmp],x,l,mid);
}
else{
insert(rs[p],rs[cmp],x,mid+1,r);
}
}
}
int query(int l,int r,int k){
int a=l,b=r,c=getlca(a,b),d=fa[c],mid,all;
a=root[dfn[a]];b=root[dfn[b]];c=root[dfn[c]];d=root[dfn[d]];
l=1,r=sz;
while(l<r){
mid=(l+r)>>1;
all=val[ls[a]]+val[ls[b]]-val[ls[c]]-val[ls[d]];
if(all>=k){
r=mid;a=ls[a];b=ls[b];c=ls[c];d=ls[d];
}
else{
l=mid+1;a=rs[a];b=rs[b];c=rs[c];d=rs[d];k-=all;
}
}
return v[l];
}
void jian(int &p,int l,int r){
p=++cnt;
if(l!=r){
int mid=(l+r)/2;
jian(ls[p],l,mid);
jian(rs[p],mid+1,r);
}
}
int main()
{
int c,b,k,p,i,x,y,s,z,lastans=0;
scanf("%d%d",&num,&p);
for(i=0;i<=num*4;i++)
son[i]=-1;
for(i=1;i<=num;i++)
{
scanf("%d",&a[i]);
}
for(i=1;i<=num-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dep[1]=1;
build(1);
dfs(1,1);

for(i=1;i<=num;i++){
v[i]=pai[i]=a[i];
}
sort(v+1,v+num+1);
sz=unique(v+1,v+num+1)-v-1;
jian(root[0],1,sz);
for(i=1;i<=num;i++){
pai[i] = lower_bound(v + 1, v + 1 + sz, a[i]) - v;
}
for(i=1;i<=num;i++){
int t=real[i];
insert(root[i],root[dfn[fa[t]]],pai[t],1,sz);
}
while(p--){
scanf("%d%d%d",&c,&b,&k);
c=c^lastans;
lastans=query(c,b,k);
printf("%d\n",lastans);
}
return 0;
}


BZOJ 10628 Luogu 2633
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: