您的位置:首页 > 其它

2588: Spoj 10628. Count on a tree[可持久化线段树+倍增lca]

2014-10-01 15:06 441 查看
今天才知道可持久化线段树其实差不多就是主席树了。所以学习主席树就用复习可持久化线段树代替了。

本来以为会是一个轻松愉快的过程,结果痛苦得要死。

每一个节点都以其父节点为历史版本加点,利用主席树就可以实现。

思路比较清楚:用T[u]+T[v]-T[lca(u,v)]-T[f[lca(u,v)]]判断向左查询还是向右查询。

刚开始是直接将节点的值添加到线段树内,但是TLE了。

顿时整个人都不好了,只好参考神犇的代码,发现少了一步离散化QAQ,好像真的忘了来着。

然后你以为我就A了?开玩笑。

无限RE...

然后不停尝试调大数组,在把lca数组的第二维调到40后A了。

果然又忘了C++数组的特性了。。应该把数组多开一点的。

---------------------------------------------------------------------------------------------------------------------------------------

速度不快,但是代码很短。。真的挺短的。

Code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define R(x) T[T[x].r]
#define L(x) T[T[x].l]
using namespace std;
const int N=200010,INF=~0u>>1;
struct list{
int p;
list* next;
list(){}
inline list* Set(int _p,list* _next){
p=_p; next=_next;
return this;
}
}T0[N<<1],*head
;int data=0;
struct Seg_Tree{
int l,r;
int sum;
}T[N<<4];
int root
,cnt=0,size=1;
int n,m,v
,v0
;
int par
[40],dep
;
int ans,lastans=0,pub;

int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int d=dep[x]-dep[y];
for(int i=0;i<=20;i++) if((1<<i)&d) x=par[x][i];
for(int i=20;i>=0;i--)
if(par[x][i]!=par[y][i])
{x=par[x][i];y=par[y][i];}
if(x==y) return x;
else return par[x][0];
}
void Addedge(int u,int v){
head[u]=(T0+(data++))->Set(v,head[u]);
head[v]=(T0+(data++))->Set(u,head[v]);
}
void Ins(int &p,int pf,int val,int l,int r){
int mid=(l+r)>>1;
T[p=cnt++]=T[pf];
if (l==r){
T[p].sum++;
return;
}if (mid+1<=val) Ins(T[p].r,T[pf].r,val,mid+1,r);
else Ins(T[p].l,T[pf].l,val,l,mid);
T[p].sum=L(p).sum+R(p).sum;
}
void Pre(int &p,int l,int r){
int mid=(l+r)>>1;
p=cnt++; T[p].sum=0;
if(l==r) return;
Pre(T[p].l,l,mid);
Pre(T[p].r,mid+1,r);
}
void dfs(int p,int f){
dep[p]=dep[f]+1; par[p][0]=f;
for(int i=1;(1<<i)<=dep[p];i++) par[p][i]=par[par[p][i-1]][i-1];
Ins(root[p],root[f],v[p],1,size);
for(list *t=head[p];t;t=t->next)
if(t->p!=f) dfs(t->p,p);
}
void Query(int x,int y,int f,int pf,int k,int l,int r){
if(l==r){
ans=l;
return;
}int mid=(l+r)>>1;
int ldelta=L(x).sum+L(y).sum-L(f).sum-L(pf).sum;
if (ldelta>=k) Query(T[x].l,T[y].l,T[f].l,T[pf].l,k,l,mid);
else Query(T[x].r,T[y].r,T[f].r,T[pf].r,k-ldelta,mid+1,r);
}
int main(){
// freopen("2588.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",v0+i);
v[i]=v0[i];
}sort(v0+1,v0+n+1);
for(int i=2;i<=n;i++) if(v0[size]!=v0[i]) v0[++size]=v0[i];
for(int i=1;i<=n;i++) v[i]=lower_bound(v0+1,v0+size+1,v[i])-v0;
for(int i=1,u,v;i<=n-1;i++){
scanf("%d%d",&u,&v);
Addedge(u,v);
}
Pre(root[0],1,size);
dfs(1,0);
for(int i=1,u,vv,k;i<=m;i++){
scanf("%d%d%d",&u,&vv,&k); u^=lastans;
pub=lca(u,vv);
Query(root[u],root[vv],root[pub],root[par[pub][0]],k,1,size);
ans=v0[ans];
printf("%d",ans);
if(i!=m) printf("\n");
lastans=ans;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: