1. 程式人生 > >BZOJ4009:[HNOI2015]接水果(整體二分版)

BZOJ4009:[HNOI2015]接水果(整體二分版)

整體 二維 .cn names etc space for char fine

淺談離線分治算法:https://www.cnblogs.com/AKMer/p/10415556.html

題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=4009

樹套樹寫法:https://www.cnblogs.com/AKMer/p/10181501.html

把二維線段樹部分改成整體二分就行了。

時間復雜度:\(O(nlog^2n)\)

空間復雜度:\(O(n)\)

代碼如下:

#include <cstdio>
#include <algorithm>
using namespace std;
#define low(i) ((i)&(-(i)))

const int maxn=4e4+5;

bool bo[maxn*5];
int n,P,Q,tot,cnt,sum;int f[maxn][17];
int now[maxn],pre[maxn<<1],son[maxn<<1];
int dep[maxn],siz[maxn],dfn[maxn],ans[maxn];

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

void add(int a,int b) {
    pre[++tot]=now[a];
    now[a]=tot,son[tot]=b;
}

void dfs(int fa,int u) {
    siz[u]=1,dfn[u]=++cnt;
    f[u][0]=fa,dep[u]=dep[fa]+1;
    for(int i=1;i<17;i++)
        f[u][i]=f[f[u][i-1]][i-1];
    for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
        if(v!=fa)dfs(u,v),siz[u]+=siz[v];
}

struct Oper {
    int opt,x,y1,y2,k;

    Oper() {}

    Oper(int _opt,int _x,int _y1,int _y2,int _k) {
        opt=_opt,x=_x,y1=_y1,y2=_y2,k=_k;
    }

    bool operator<(const Oper &a)const {
        if(x==a.x)return (opt!=0)>(a.opt!=0);
        return x<a.x;
    }
}p[maxn*5],tmp[maxn*5];

struct tree_array {
    int c[maxn];

    void add(int pos,int v) {
        for(int i=pos;i<=n;i+=low(i))
            c[i]+=v;
    }

    int query(int pos) {
        int res=0;
        for(int i=pos;i;i-=low(i))
            res+=c[i];
        return res;
    }
}T;

void solve(int l,int r,int st,int ed) {
    if(ed<st)return;
    if(l==r) {
        for(int i=st;i<=ed;i++)
            if(!p[i].opt)ans[p[i].y2]=l;
        return;
    }
    int mid=(l+r)>>1,num=0;
    for(int i=st;i<=ed;i++)
        if(p[i].opt) {
            if(p[i].k<=mid) {
                bo[i]=1,num++;
                T.add(p[i].y1,p[i].opt);
                T.add(p[i].y2+1,-p[i].opt);
            }
            else bo[i]=0;
        }
        else {
            int res=T.query(p[i].y1);
            if(res>=p[i].k)bo[i]=1,num++;
            else bo[i]=0,p[i].k-=res;
        }
    for(int i=st;i<=ed;i++)
        if(p[i].opt&&p[i].k<=mid) {
            T.add(p[i].y1,-p[i].opt);
            T.add(p[i].y2+1,p[i].opt);
        }
    int ED=st,ST=st+num;
    for(int i=st;i<=ed;i++)
        if(bo[i])tmp[ED++]=p[i];
        else tmp[ST++]=p[i];
    for(int i=st;i<=ed;i++)
        p[i]=tmp[i];
    solve(l,mid,st,ED-1),solve(mid+1,r,ED,ed);
}

int main() {
    n=read(),P=read(),Q=read();
    for(int i=1;i<n;i++) {
        int x=read(),y=read();
        add(x,y),add(y,x);
    }
    dfs(0,1);
    for(int i=1;i<=P;i++) {
        int u=read(),v=read(),c=read();
        if(dfn[u]>dfn[v])swap(u,v);
        if(dfn[u]+siz[u]-1>=dfn[v]+siz[v]-1) {
            int pos=v;
            for(int i=16;~i;i--)
                if(dep[f[pos][i]]>dep[u])
                    pos=f[pos][i];
            p[++sum]=Oper(1,1,dfn[v],dfn[v]+siz[v]-1,c);
            p[++sum]=Oper(-1,dfn[pos],dfn[v],dfn[v]+siz[v]-1,c);
            p[++sum]=Oper(1,dfn[v],dfn[pos]+siz[pos],n,c);
            p[++sum]=Oper(-1,dfn[v]+siz[v],dfn[pos]+siz[pos],n,c);
        }
        else {
            p[++sum]=Oper(1,dfn[u],dfn[v],dfn[v]+siz[v]-1,c);
            p[++sum]=Oper(-1,dfn[u]+siz[u],dfn[v],dfn[v]+siz[v]-1,c);
        }
    }
    for(int i=1;i<=Q;i++) {
        int u=read(),v=read(),k=read();
        if(dfn[u]>dfn[v])swap(u,v);
        p[++sum]=Oper(0,dfn[u],dfn[v],i,k);
    }
    sort(p+1,p+sum+1);
    solve(1,1e9,1,sum);
    for(int i=1;i<=Q;i++)
        printf("%d\n",ans[i]);
    return 0;
}

BZOJ4009:[HNOI2015]接水果(整體二分版)