zoukankan      html  css  js  c++  java
  • 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
    ");
    //#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;
    }
  • 相关阅读:
    技术管理之路三、团队建设:怎么带队伍?
    技术管理之路五、管理沟通:管理的必修课!
    职场工作方法论:计划安排,时间管理的“四象限法则”
    职场工作方法论:目标管理SMART原则
    激励方法论1、马斯洛需求模型
    mybatis PageHelper 分页组件优化
    async 和 await
    spring cloud 负载均衡 平滑上下线
    vue 重新渲染组件
    spring cloud 超时整理
  • 原文地址:https://www.cnblogs.com/20020723YJX/p/9376791.html
Copyright © 2011-2022 走看看