zoukankan      html  css  js  c++  java
  • HDU4822-Tri-War

    题目

    给出一颗树,(m)次询问树上不相同的三个点(A,B,C)。我们称一个点(x)(A)占领当且仅当(dist(A,x)>dist(B,x),dist(A,x)>dist(C,x))

    (A,B,C)这三个点分别占领了多少个点。

    (n,mle 10^5)

    分析

    如果是两个点的话,我们找到他们的中点,讨论一下即可。现在有三个点,那么我们对(A),分别算一下与(B)(C)的dfn序区间,用线段树做一下区间求交即可。也可以扫描线求交,不过最多就四个区间。

    代码

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read() {
        int x=0,f=1;
        char c=getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
        for (;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=1e5+1;
    const int maxj=17;
    int f[maxn][maxj],dep[maxn],dfx,first[maxn],second[maxn],n;
    struct TREE {
        vector<int> g[maxn];
        inline void clear(int n) {
            memset(f,0,sizeof f),memset(dep,0,sizeof dep);
            memset(first,0,sizeof first),memset(second,0,sizeof second);
            for (int i=1;i<=n;++i) g[i].clear();
            dfx=0;
        }
        inline void add(int x,int y) {g[x].push_back(y);}
        void dfs(int x,int fa) {
            f[x][0]=fa;
            dep[x]=dep[fa]+1;
            first[x]=++dfx;
            for (int v:g[x]) if (v!=fa) dfs(v,x);
            second[x]=dfx;
        }
        void run() {
            dfs(1,1);
            for (int j=1;j<maxj;++j) for (int i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1];
        }
        int lca(int x,int y) {
            if (dep[x]<dep[y]) swap(x,y);
            for (int j=maxj-1;j>=0;--j) if (dep[f[x][j]]>=dep[y]) x=f[x][j];
            if (x==y) return x;
            for (int j=maxj-1;j>=0;--j) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
            return f[x][0];
        }
        int jump(int x,int y) {
            for (int j=maxj-1;j>=0;--j) if ((y>>j)&1) x=f[x][j];
            return x;
        }
    } tree;
    struct SGT {
        struct node {
            int zero,one,two,tag;
            int tic;
        } t[maxn<<2];
        int tim;
        SGT ():tim(0) {}
        void flow() {++tim;}
        void doit(int x) {
            t[x].two=t[x].one,t[x].one=t[x].zero,t[x].zero=0;
            ++t[x].tag;
        }
        void pushdown(int x,int L,int mid,int R) {
            newnode(x<<1,L,mid),newnode(x<<1|1,mid+1,R);
            for (int &tmp=t[x].tag;tmp;--tmp) doit(x<<1),doit(x<<1|1);
        }
        void update(int x,int L,int mid,int R) {
            newnode(x<<1,L,mid),newnode(x<<1|1,mid+1,R);
            t[x].zero=t[x<<1].zero+t[x<<1|1].zero;
            t[x].one=t[x<<1].one+t[x<<1|1].one;
            t[x].two=t[x<<1].two+t[x<<1|1].two;
        }
        void newnode(int x,int L,int R) {
            if (t[x].tic!=tim) t[x].tic=tim,t[x].one=t[x].two=0,t[x].zero=R-L+1,t[x].tag=0;
        }
        void inc(int x,int L,int R,int l,int r) {
            newnode(x,L,R);
            if (L==l && R==r) {
                doit(x);
                return;
            }
            int mid=(L+R)>>1;
            pushdown(x,L,mid,R);
            if (r<=mid) inc(x<<1,L,mid,l,r); else
            if (l>mid) inc(x<<1|1,mid+1,R,l,r); else 
            inc(x<<1,L,mid,l,mid),inc(x<<1|1,mid+1,R,mid+1,r);
            update(x,L,mid,R);
        }
        void inc(int l,int r) {
            if (l>r) return;
            inc(1,1,n,l,r);
        }
        int query() {
            return t[1].two;
        }
    } sgt;
    void deal(int a,int b) {
        int l=tree.lca(a,b);
        if (a==l) {
            int d=dep[b]-dep[a];
            int jp=d>>1;
            int p=tree.jump(b,jp);
            sgt.inc(1,first[p]-1);
            sgt.inc(second[p]+1,n);
        } else if (b==l) {
            int d=dep[a]-dep[b];
            int jp=(d-1)>>1;
            int p=tree.jump(a,jp);
            sgt.inc(first[p],second[p]);
        } else {
            int ad=dep[a]-dep[l],bd=dep[b]-dep[l];
            if (ad==bd) {
                int p=tree.jump(a,ad-1);
                sgt.inc(first[p],second[p]);
            } else if (ad>bd) {
                int d=ad+bd,jp=(d-1)>>1;
                int p=tree.jump(a,jp);
                sgt.inc(first[p],second[p]);
            } else if (ad<bd) {
                int d=ad+bd,jp=d>>1;
                int p=tree.jump(b,jp);
                sgt.inc(1,first[p]-1);
                sgt.inc(second[p]+1,n);
            }
        }
    }
    int Ans(int a,int b,int c) {
        sgt.flow();
        deal(a,b);
        deal(a,c);
        return sgt.query();
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("test.in","r",stdin);
    #endif
        int T=read();
        while (T--) {
            n=read();
            tree.clear(n);
            for (int i=1;i<n;++i) {
                int x=read(),y=read();
                tree.add(x,y),tree.add(y,x);
            }
            tree.run();
            int q=read();
            while (q--) {
                int fir=read(),sec=read(),thr=read();
                int afir=Ans(fir,sec,thr);
                int asec=Ans(sec,fir,thr);
                int athr=Ans(thr,fir,sec);
                printf("%d %d %d
    ",afir,asec,athr);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    053-157
    053-496
    053-128
    053-167
    053-250
    053-674
    离职申请
    日记


  • 原文地址:https://www.cnblogs.com/owenyu/p/7146124.html
Copyright © 2011-2022 走看看