您的位置:首页 > 其它

主席树+dfs SPOJ BZOJ2588 Count on a tree

2017-12-09 21:36 260 查看

这道题我由于智障错误导致一直错。

在树上建主席树,加上lca思想,很简单。

#include<bits/stdc++.h>
using namespace std;
const int N=200005;
struct node
{
int to,nex;
}e[N<<1];
struct tree
{
int l,r,s;
}t[2000005];
int n,m,cnt,cn,mx,pre,head
,f
[21],a
,rt
,d
;
vector<int>v;
inline int get(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
void add(int x,int y)
{
e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;
}
void update(int &x,int l,int r,int p,int num)
{
x=++cn;t[x]=t

;t[x].s++;int mid=l+r>>1; if(l==r)return ; if(mid>=num)update(t[x].l,l,mid,t[p].l,num); else update(t[x].r,mid+1,r,t[p].r,num); } void dfs(int x,int fa) { update(rt[x],1,mx,rt[fa],get(a[x]));f[x][0]=fa;d[x]=d[fa]+1; for(int i=1;i<=20;++i) if(d[x]>=(1<<i)) f[x][i]=f[f[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].nex) { int y=e[i].to; if(y==fa)continue; dfs(y,x); } } int lca(int x,int y) { if(d[x]<d[y])swap(x,y); int tmp=d[x]-d[y]; for(int i=20;i>=0;i--) if(tmp&(1<<i))x=f[x][i]; for(int i=20;i>=0;i--) { if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; } return x==y?x:f[x][0]; } int query(int l,int r,int rt1,int rt2,int rt3,int rt4,int k) { if(l==r){ pre=v[l-1];return l; } int sum=t[t[rt1].l].s+t[t[rt2].l].s-t[t[rt3].l].s-t[t[rt4].l].s; int mid=(l+r)>>1; if(sum>=k)return query(l,mid,t[rt1].l,t[rt2].l,t[rt3].l,t[rt4].l,k); else return query(mid+1,r,t[rt1].r,t[rt2].r,t[rt3].r,t[rt4].r,k-sum); } int main() { //freopen("rand.out","r",stdin); //freopen("my.out","w",stdout); int x,y,k; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) { scanf("%d",&a[i]);v.push_back(a[i]); } sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());mx=v.size(); for(int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y);add(y,x); } dfs(1,0); for(int i=1;i<=m;++i) { scanf("%d%d%d",&x,&y,&k); int z=lca(pre^x,y); printf("%d",v[query(1,mx,rt[pre^x],rt[y],rt[z],rt[f[z][0]],k)-1]); if(i<m) puts(""); } return 0; }

[p]BZOJ最后换行会PE。。。。

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