洛谷P1505 [国家集训队]旅游(BZOJ2157)

树链剖分

洛谷题目传送门
BZOJ题目传送门

操作有点多的裸树剖。套路下放边权后就是打板子。注意操作的时候不要包括LCA。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 20005
#define F inline
using namespace std;
struct edge{ int nxt,to,d; }ed[N<<1];
struct tree{ int l,r,s,mx,mn,f; }t[N<<2];
int n,k,ti,a[N],w[N],h[N],tp[N],sz[N],to[N],fa[N],id[N],in[N],dep[N];
F char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    return l==r?EOF:*l++;
}
F int _read(){
    int x=0,f=1; char ch=readc(),c;
    while (!isdigit(ch)&&!isupper(ch)){ if (ch=='-') f=-1; ch=readc(); }
    if (isupper(ch))
        if (ch=='C'||ch=='N') return ch;
        else return c=readc(),ch=readc(),c;
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x*f; 
}
F void writec(int x){
    if (x<0) putchar('-'),x=-x;
    if (x>9) writec(x/10); putchar(x%10+48);
}
F void _write(int x){ writec(x),puts(""); }
#define addedge(x,y,z) ed[++k]=(edge){h[x],y,z},h[x]=k
void dfs1(int x){
    sz[x]=1,dep[x]=dep[fa[x]]+1;
    for (int i=h[x],v;i;i=ed[i].nxt)
        if ((v=ed[i].to)!=fa[x]){
            fa[v]=x,w[v]=ed[i].d,dfs1(v),sz[x]+=sz[v];
            a[(i>>1)+(i&1)]=v; if (sz[v]>sz[to[x]]) to[x]=v;
        }
}
void dfs2(int x){
    if (to[in[id[x]=++ti]=x]) tp[to[x]]=tp[x],dfs2(to[x]);
    for (int i=h[x],v;i;i=ed[i].nxt)
        if ((v=ed[i].to)!=fa[x]&&v!=to[x])
            tp[v]=v,dfs2(v);
}
F void updt(int x){
    t[x].s*=-1,t[x].mn*=-1,t[x].mx*=-1;
    swap(t[x].mn,t[x].mx),t[x].f^=1;
}
F void pshd(int x){ updt(x<<1),updt(x<<1|1); }
F void pshp(tree &x,tree l,tree r){
    x.s=l.s+r.s,x.mx=max(l.mx,r.mx),x.mn=min(l.mn,r.mn);
}
void build(int x,int l,int r){
    int p=w[in[l]],mid=l+r>>1; t[x].l=l,t[x].r=r;
    if (l==r) return void(t[x]=(tree){l,r,p,p,p});
    build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    pshp(t[x],t[x<<1],t[x<<1|1]);
}
void mdfy1(int x,int p,int w){
    if (t[x].l==t[x].r) return void(t[x].s=t[x].mn=t[x].mx=w);
    if (t[x].f) pshd(x),t[x].f=0; int mid=t[x].l+t[x].r>>1;
    mdfy1(x<<1|(p>mid),p,w),pshp(t[x],t[x<<1],t[x<<1|1]);
}
void mdfy2(int x,int l,int r){
    if (t[x].l>r||t[x].r<l) return;
    if (t[x].l>=l&&t[x].r<=r) return updt(x);
    if (t[x].f) pshd(x),t[x].f=0;
    mdfy2(x<<1,l,r),mdfy2(x<<1|1,l,r);
    pshp(t[x],t[x<<1],t[x<<1|1]);
}
tree srch(int x,int l,int r){
    tree ret={0,0,0,-1e9,1e9,0},L,R;
    if (t[x].l>r||t[x].r<l) return ret;
    if (t[x].l>=l&&t[x].r<=r) return t[x];
    if (t[x].f) pshd(x),t[x].f=0;
    pshp(ret,srch(x<<1,l,r),srch(x<<1|1,l,r));
    return ret;
}
F void nsrt(int x,int y){
    while (tp[x]!=tp[y]){
        if (dep[tp[x]]<dep[tp[y]]) swap(x,y);
        mdfy2(1,id[tp[x]],id[x]),x=fa[tp[x]];
    }
    if (dep[x]<dep[y]) swap(x,y);
    mdfy2(1,id[y]+1,id[x]);
}
F tree find(int x,int y){
    tree ans={0,0,0,-1e9,1e9,0};
    while (tp[x]!=tp[y]){
        if (dep[tp[x]]<dep[tp[y]]) swap(x,y);
        pshp(ans,ans,srch(1,id[tp[x]],id[x])),x=fa[tp[x]];
    }
    if (dep[x]<dep[y]) swap(x,y);
    pshp(ans,ans,srch(1,id[y]+1,id[x])); return ans;
}
int main(){
    n=_read();
    for (int i=1,x,y,z;i<n;i++){
        x=_read()+1,y=_read()+1,z=_read();
        addedge(x,y,z),addedge(y,x,z);
    }
    dfs1(1),tp[1]=1,dfs2(1),build(1,1,n);
    for (int q=_read();q;q--){
        int f=_read(),x=_read()+1,y=_read()+1;
        switch (f){
            case 'C': mdfy1(1,id[a[x-1]],y-1); break;
            case 'N': nsrt(x,y); break;
            case 'U': _write(find(x,y).s); break;
            case 'A': _write(find(x,y).mx); break;
            case 'I': _write(find(x,y).mn); break;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/80596166