BZOJ2588 Count on a tree

 在下可能是被秀了,又调了2h+,接近3h,,

题面传送门

去重时要减一!!

要减一!!

减一!!

这是一个悲伤的故事,不减会在BZOJ上RE(为什么洛谷上不会...),然后就是最后一个输出不输出空格,不然BZOJ上PE(洛谷上还是不会...)

主席树裸题,具体操作都会,在下就不乱扯了,把主席树从序列上改到树上就行了

说的那么玄,其实就是root[i]从root[i-1]来变成从root[fa[i]]来就行了

查询区间为:root[u]的线段树+root[v]的线段树-root[lca(u,v)]的线段树-root[fa[lca(u,v)]]的线段树

偷懒不想树剖,直接倍增了

这次没写注释,需要请留言

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define ll long long
#define re register
#define inf 0x3f3f3f3f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug\n");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
//const ll mod;
const ll MAXN=1e5+10;
inl ll read() {
    re ll x = 0; re int f = 1;
    char ch = getchar();
    while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
    while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x * f;
}
inl char readc() {
    char ch=getchar();
    while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
    return ch;
}
inl void write(re ll x){
    if(x>=10)write(x/10);
    putchar(x%10+'0');
}
inl void writeln(re ll x){
    if(x<0) {x=-x;putchar('-');}
    write(x); puts("");
}
inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
inl void FR() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
inl void FC() {
    fclose(stdin);
    fclose(stdout);
}
ll n,m,ssw[MAXN],cnt,head[MAXN],fa[MAXN][25],depth[MAXN],tot,root[MAXN];
ll cpy[MAXN],top;
struct Node {
    ll u,v,nxt;
}e[MAXN<<1];
struct NODE {
    ll lson,rson,cnt;
}ss[MAXN<<5];
inl void adde(ll u,ll v) {
    e[++cnt].nxt=head[u];head[u]=cnt;
    e[cnt].u=u;e[cnt].v=v;
}
inl void update(ll x) {ss[x].cnt=ss[ss[x].lson].cnt+ss[ss[x].rson].cnt;}
ll insert(ll x,ll l,ll r,ll pos) {
    ll t=++tot;ss[t]=ss[x];ss[t].cnt++;
    if(l==r) return t;
    re ll mid=(l+r)>>1;
    if(pos<=mid) ss[t].lson=insert(ss[x].lson,l,mid,pos);
    else ss[t].rson=insert(ss[x].rson,mid+1,r,pos);
    update(t);
    return t;
}
void dfs(ll x,ll Fa) {
    root[x]=insert(root[Fa],1,top,ssw[x]);
    depth[x]=depth[Fa]+1;fa[x][0]=Fa;
    for(re ll i=1;i<=20;i++) {
        fa[x][i]=fa[fa[x][i-1]][i-1];
        if(fa[x][i]==0) break ;
    }
    for(re ll h=head[x];h;h=e[h].nxt) {
        re ll v=e[h].v;
        if(v==Fa) continue ;
        dfs(v,x);
    }
    return ;
}
ll lca(ll x,ll y) {
    if(depth[x]>depth[y]) swap(x,y);
    for(re ll i=20;~i;i--) {
        if(depth[fa[y][i]]<depth[x]) continue ;
        y=fa[y][i];
    }
    if(x==y) return x;
    for(re ll i=20;~i;i--) {
        if(fa[x][i]==fa[y][i]) continue ;
        x=fa[x][i],y=fa[y][i];
    }
    return fa[x][0];
}
ll query(ll x,ll y,ll z,ll s,ll l,ll r,ll k) {
    if(l==r) return l;
    ll sc=ss[ss[x].lson].cnt+ss[ss[y].lson].cnt-ss[ss[z].lson].cnt-ss[ss[s].lson].cnt;
    ll mid=(l+r)>>1;
    if(sc>=k) return query(ss[x].lson,ss[y].lson,ss[z].lson,ss[s].lson,l,mid,k);
    else return query(ss[x].rson,ss[y].rson,ss[z].rson,ss[s].rson,mid+1,r,k-sc);
}
int main(){
//    FR(); 
    n=read(),m=read();
    top=n;
    for(re ll i=1;i<=n;i++) ssw[i]=read(),cpy[i]=ssw[i];
    sort(cpy+1,cpy+n+1);
    top=unique(cpy+1,cpy+n+1)-cpy-1;
    for(re ll i=1;i<=n;i++) ssw[i]=lower_bound(cpy+1,cpy+top+1,ssw[i])-cpy;
    for(re ll i=1;i<n;i++) {
        re ll x=read(),y=read();
        adde(x,y);adde(y,x);
    }
    dfs(1,0);ll lastans=0;
    for(re ll i=1;i<=m;i++) {
        ll u=read()^lastans,v=read(),k=read();
        ll x=lca(u,v);
        lastans=cpy[query(root[u],root[v],root[x],root[fa[x][0]],1,top,k)];
        write(lastans);
        if(i!=m) puts("");
    }
//    FC();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/20020723YJX/p/9376791.html