您的位置:首页 > 其它

BZOJ2588: Spoj 10628. Count on a tree

2016-07-19 00:07 267 查看

裸的树上主席树。一般的主席树每个节点相当于一个前缀和,树上主席树每个节点相当于到根的和,可持久化的时候以树上的父亲为上一个版本。

注意最后一行行末不能输出换行,否则会PE。

upd: 用可持久化trie重写了一遍,和主席树本质相同写法不同,变快了。

#include<algorithm>
#include<cstdio>
#define lb lower_bound
using namespace std;
const int N=1e5+5;
typedef struct node*ptr;
struct node{
ptr i,j;int s;
}e[N*17];
ptr a=e,f
;
void ins(int j,ptr*o){
for(int i=16;~i;--i){
*++a=**o,*o=a;
if(j>>i&1)o=&(*o)->j;
else
++(*o)->s,o=&(*o)->i;
}
}
int ask(int k,ptr s,ptr t,ptr u,ptr v){
int j=0;
for(int i=16;~i;--i){
int l=s->s+t->s-u->s-v->s;
if(k<=l)s=s->i,t=t->i,u=u->i,v=v->i;
else
k-=l,j|=1<<i,s=s->j,t=t->j,u=u->j,v=v->j;
}
return j;
}
struct edge{
int v;edge*s;
}z[N*2];
edge*b=z,*h
;
void ins(int u,int v){
edge s={v,h[u]};
*(h[u]=b++)=s;
}
typedef int arr
;
arr w,p,d,r,y,c,g;
void dfs1(int u){
f[u]=f[p[u]];
ins(w[u],f+u);
r[u]=1;
for(edge*i=h[u];i;i=i->s)
if(i->v!=p[u]){
d[i->v]=d[p[i->v]=u]+1;
dfs1(i->v);
r[u]+=r[i->v];
if(r[i->v]>r[c[u]])
c[u]=i->v;
}
}
int lca(int s,int t){
for(;y[s]!=y[t];s=p[y[s]])
if(d[y[s]]<d[y[t]])s^=t,t^=s,s^=t;
return d[s]<d[t]?s:t;
}
struct buf{
char z[1<<23],*s;
char e[9<<17],*p;
buf():s(z),p(e){
z[fread(z,1,sizeof z,stdin)]=0;
}
~buf(){fwrite(e,1,p-e,stdout);}
operator int(){
int x=0;
while(*s<48)++s;
while(*s>32)
x=x*10+*s++-48;
return x;
}
void out(int x){
static char z[12];
char*i=z;
if(!x)*p++=48;
else{
while(x){
int y=x/10;
*i++=x-y*10+48,x=y;
}
while(i!=z)*p++=*--i;
}
}
}it;
int main(){
*(*f=e)=(node){e,e};
int n=it,m=it;
for(int i=1;i<=n;++i)
g[i-1]=w[i]=it;
sort(g,g+n);
for(int i=1;i<=n;++i)
w[i]=lb(g,g+n,w[i])-g;
for(int i=2;i<=n;++i){
int s=it,t=it;
ins(s,t),ins(t,s);
}
dfs1(1);
for(int i=1;i<=n;++i)
if(c[p[i]]!=i)
for(int j=i;j;j=c[j])y[j]=i;
int l=0;
while(m--){
int s=it^l,t=it,u=lca(s,t);
it.out(l=g[ask(it,f[s],f[t],f[u],f[p[u]])]);
if(m)*it.p++=10;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: