BZOJ3435: [Wc2014]紫荆花之恋

BZOJ3435: [Wc2014]紫荆花之恋

https://lydsy.com/JudgeOnline/problem.php?id=3435

分析:

  • 如果不强制在线,可以将树存下来用点分树来查询和修改。
  • \(dis(i,j)-R_j\le R_i\),是个使用点分树维护的经典问题。
  • 如果每次直接插到父亲下面会使得点分树不平衡,利用替罪羊重构的思想在不平衡的时候重构一下即可,这里重构一下即对这个子树(连通块)进行点分治。
  • 内层如果用线段树会炸空间,于是我内层也使用替罪羊来维护。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define N 100050
#define M 14000000
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
typedef long long ll;
#define AL1 0.8
#define AL2 0.9
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) 
int rd() {
    int x=0,f=1; char s=nc();
    while(s<'0') {if(s=='-') f=-1; s=nc();}
    while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    return x*f;
}
int head[N],to[N<<1],nxt[N<<1],fa[N][20],Lg[N],dep[N],cnt;
ll dis[N];
int sz[M],rr[N],ch[M][2],f[M],val[M],reimu,n,fb[N],tot;
int Sta[M],top;
vector<int>V[N];
int all[N],vis[N],visc,siz[N],fk[N],rot,used[N];
#define GG(p) (max(sz[ls],sz[rs])>AL1*sz[p])
inline void add(int u,int v) {
    to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
int newnode(int v) {
    int p;
    if(!top) p=++reimu;
    else {
        p=Sta[top--];
        sz[p]=ls=rs=f[p]=0;
    }
    val[p]=v;
    return p;
}
int S[M],tp,koishi;
struct SGT {
    int root;
    void insert(int &p,int v,int fa) {
        if(!p) {
            p=newnode(v); sz[p]=1; f[p]=fa; return ;
        }
        sz[p]++;
        if(val[p]>v) insert(ls,v,p);
        else insert(rs,v,p);
        if(GG(p)) koishi=p;
    }
    int ask(int p,int x) {
        if(!p) return 0;
        if(val[p]<=x) return ask(rs,x)+sz[ls]+1;
        else return ask(ls,x);
    }
    void dfs(int p) {
        if(ls) dfs(ls);
        S[++tp]=p;
        if(rs) dfs(rs);
    }
    int build(int l,int r,int fa) {
        int mid=(l+r)>>1,p=S[mid];
        f[p]=fa; ls=rs=0;
        if(!f[p]) root=p;
        if(l<mid) ls=build(l,mid-1,p);
        if(r>mid) rs=build(mid+1,r,p);
        sz[p]=sz[ls]+sz[rs]+1;
        return p;
    }
    void Ins(int v) {
        koishi=0;
        insert(root,v,0);
        if(koishi) {
            tp=0;
            int k=get(koishi),fa=f[koishi];
            dfs(koishi); 
            ch[fa][k]=build(1,tp,fa);
        }
    }
    void asd(int p) {
        if(ls) asd(ls);
        Sta[++top]=p;
        if(rs) asd(rs);
    }
    void rec() {
        asd(root); root=0;
    }
}F[N][2];
int lca(int x,int y) {
    int i;
    if(dep[x]<dep[y]) swap(x,y);
    for(i=Lg[dep[x]];i>=0;i--) {
        if(fa[x][i]&&dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    }
    if(x==y) return x;
    for(i=Lg[dep[x]];i>=0;i--) if(fa[x][i]&&fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
ll Dis(int x,int y) {return dis[x]+dis[y]-2*dis[lca(x,y)];}
void gr(int x,int y) {
    int i;
    siz[x]=1; fk[x]=0;
    for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]&&vis[to[i]]==visc) {
        gr(to[i],x); siz[x]+=siz[to[i]];
        fk[x]=max(fk[x],siz[to[i]]);
    }
    fk[x]=max(fk[x],tot-siz[x]);
    if(fk[x]<fk[rot]) rot=x;
}
void gd(int x,int y,int rt) {
    int i;
    all[rt]++;
    F[rt][0].Ins(Dis(x,rt)-rr[x]);
    F[rt][1].Ins(Dis(x,fb[rt])-rr[x]);
    V[rt].push_back(x);
    for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]&&vis[to[i]]==visc) {
        gd(to[i],x,rt);
    }
}
void solve(int x) {
    used[x]=1;
    int i,al=tot;
    V[x].clear();
    all[x]=0;
    F[x][0].rec(); F[x][1].rec();
    gd(x,0,x);
    for(i=head[x];i;i=nxt[i]) if(!used[to[i]]&&vis[to[i]]==visc) {
        tot=siz[to[i]]; if(tot>siz[x]) tot=al-siz[x];
        rot=0; gr(to[i],x); fb[rot]=x; solve(rot);
    }
}
void update(int x) {
    int t;
    int kksk=0;
    for(t=x;t;t=fb[t]) {
        all[t]++;
        F[t][0].Ins(Dis(x,t)-rr[x]);
        F[t][1].Ins(Dis(x,fb[t])-rr[x]);
        V[t].push_back(x);
    }
    for(t=x;fb[t];t=fb[t]) {
        if(all[t]>all[fb[t]]*AL2) {
            kksk=fb[t];
        }
    }
    if(kksk) {
        int p=kksk;
        int i,lim=V[p].size(),ff=fb[p];
        visc++;
        for(i=0;i<lim;i++) {
            vis[V[p][i]]=visc;
            used[V[p][i]]=0;
        }
        rot=0;
        tot=lim; 
        gr(p,0);
        fb[rot]=ff;
        solve(rot);
    }
}
int query(int x,int k) {
    int t,re=0,lst=0;
    ll len;
    for(t=x;t;t=fb[t]) {
        len=Dis(x,t);
        re+=F[t][0].ask(F[t][0].root,k-len);
        if(lst) re-=F[lst][1].ask(F[lst][1].root,k-len);
        lst=t;
    }
    return re;
}
int main() {
    fk[0]=1<<30;
    rd(); n=rd();
    int i,x,y,j;
    rd(); rd(); rr[1]=rd();
    for(i=1,Lg[0]=-1;i<=n;i++) Lg[i]=Lg[i>>1]+1;
    dep[1]=1;
    ll ans=0;
    F[1][0].Ins(-rr[1]);
    V[1].push_back(1); 
    all[1]=1;
    puts("0");
    for(i=2;i<=n;i++) {
        x=rd(); y=rd(); rr[i]=rd();
        x^=(ans%1000000000);
        dis[i]=dis[x]+y; dep[i]=dep[x]+1; fa[i][0]=x; fb[i]=x;
        for(j=1;(1<<j)<=n;j++) fa[i][j]=fa[fa[i][j-1]][j-1];
        add(x,i); add(i,x);
        ans+=query(i,rr[i]);
        printf("%lld\n",ans);
        update(i);
    }
}

猜你喜欢

转载自www.cnblogs.com/suika/p/10164879.html
今日推荐