BZOJ3531 [Sdoi2014]旅行(洛谷P3313)

版权声明:蒟蒻Blog随意转载 https://blog.csdn.net/a1799342217/article/details/81812833

树链剖分 (线段树动态开点)

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

学了发线段树动态开点。

其实动态开点就是先不建树,每次修改的时候再往下建。这时左右儿子是编号的而不是原来的 2 2 + 1 。可以发现每次新建的节点数为 log n ,那么总空间复杂度就是 n log n 的。

这道题的话对每种颜色都开一个线段树。然后树剖上去+动态开点就好了。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
using namespace std;
struct edge{ int nxt,to; }ed[N<<1];
struct tree{ int ls,rs,l,r,mx,s; }t[N<<6];
int n,m,k,ti,nd,h[N],w[N],c[N],rt[N],sz[N],to[N],tp[N],fa[N],dep[N],in[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; char ch=readc();
    while (!isdigit(ch)&&!isupper(ch)) ch=readc();
    if (isupper(ch)) return ch=readc();
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x;
}
F void writec(int x){ if (x>9) writec(x/10); putchar(x%10+48); }
F void _write(int x){ writec(x),puts(""); }
#define add(x,y) ed[++k]=(edge){h[x],y},h[x]=k
void dfs1(int x){
    dep[x]=dep[fa[x]]+1,sz[x]=1;
    for (int i=h[x],v;i;i=ed[i].nxt)
        if ((v=ed[i].to)!=fa[x]){
            fa[v]=x,dfs1(v),sz[x]+=sz[v];
            if (sz[to[x]]<sz[v]) to[x]=v;
        }
}
void dfs2(int x){
    in[x]=++ti;
    if (to[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);
}
#define max(x,y) ((x)>(y)?(x):(y))
void mdfy(int &x,int l,int r,int p,int w){
    if (!x) x=++nd; t[x].l=l,t[x].r=r; int mid;
    if (l==r) return void(t[x].mx=t[x].s=w);
    if ((mid=l+r>>1)>=p) mdfy(t[x].ls,l,mid,p,w);
    else mdfy(t[x].rs,mid+1,r,p,w);
    t[x].s=t[t[x].ls].s+t[t[x].rs].s;
    t[x].mx=max(t[t[x].ls].mx,t[t[x].rs].mx);
}
tree srch(int x,int l,int r){
    tree s,ls,rs; s.mx=s.s=0;
    if (t[x].l>r||t[x].r<l) return s;
    if (t[x].l>=l&&t[x].r<=r) return t[x];
    ls=srch(t[x].ls,l,r),rs=srch(t[x].rs,l,r);
    return s.s=ls.s+rs.s,s.mx=max(ls.mx,rs.mx),s;
}
tree find(int x,int y){
    tree ans,p; ans.s=ans.mx=0; int cc=c[x];
    while (tp[x]!=tp[y]){
        if (dep[tp[x]]<dep[tp[y]]) swap(x,y);
        p=srch(rt[cc],in[tp[x]],in[x]);
        ans.s+=p.s,ans.mx=max(ans.mx,p.mx),x=fa[tp[x]];
    }
    if (dep[x]<dep[y]) swap(x,y);
    p=srch(rt[cc],in[y],in[x]);
    return ans.s+=p.s,ans.mx=max(ans.mx,p.mx),ans;
}
int main(){
    n=_read(),m=_read();
    for (int i=1;i<=n;i++)
        w[i]=_read(),c[i]=_read();
    for (int i=1,x,y;i<n;i++)
        x=_read(),y=_read(),add(x,y),add(y,x);
    dfs1(1),tp[1]=1,dfs2(1);
    for (int i=1;i<=n;i++)
        mdfy(rt[c[i]],1,n,in[i],w[i]);
    while (m--){
        int f=_read(),x=_read(),y=_read();
        if (f=='C'){
            mdfy(rt[c[x]],1,n,in[x],0);
            mdfy(rt[c[x]=y],1,n,in[x],w[x]);
        }
        else if (f=='W')
            mdfy(rt[c[x]],1,n,in[x],w[x]=y);
        else _write(f=='S'?find(x,y).s:find(x,y).mx);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/81812833
今日推荐