[学习笔记] Mys_C_K的独立集好题 - 动态dp - 树剖 - 线段树

注意修改的时候要先从上到下减去,然后修改好后从下到上加上。
注意轻边的信息是真的dp值,特判空信息。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define lint int
#define gc getchar()
#define N 200010
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch,sgn=1;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
    if(ch=='-') sgn=-1,x=0;else x=ch^'0';
    while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
    return x*sgn;
}
struct edges{
    int to,pre;
}e[N<<1];int h[N],etop,fa[N],top[N],son[N],in[N];
lint f[N],g[N];int sz[N],vt[N],bot[N],dfs_clock,L[N];
inline int add_edge(int u,int v)
{
    return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
struct answer{
    lint w[2][2];bool ept;
    answer(lint f=0,lint g=0) { this->init(f,g,1); }
    inline lint init(lint f,lint g,bool e)
    {   return w[1][1]=f,w[0][0]=g,w[0][1]=w[1][0]=0,ept=e; }
    inline answer operator=(const answer &ans)
    {   rep(i,0,1) rep(j,0,1) w[i][j]=ans.w[i][j];ept=ans.ept;return *this; }
    inline lint f() { return max(w[1][0],w[1][1]); }
    inline lint g() { return max(w[0][0],w[0][1]); }
    inline lint ans() { return max(f(),g()); }
    inline bool empty()const { return ept; }
    inline int show()
    {   return debug(w[0][0])sp,debug(w[0][1])sp,debug(w[1][0])sp,debug(w[1][1])sp,debug(ept)ln,0;  }
}ans;
inline answer merge_ans(const answer &a,const answer &b)
{
    if(a.empty()) return b;static answer ans;
    ans.init(0,0,0);
    rep(i,0,1) rep(j,0,1) rep(p,0,1) rep(q,0,1-p)
        ans.w[i][j]=max(ans.w[i][j],a.w[i][p]+b.w[q][j]);
    return ans;
}
struct segment{
    int l,r;answer ans;
    segment *ch[2];
}*rt;
lint build(segment* &rt,int l,int r)
{
    rt=new segment,rt->l=l,rt->r=r;int mid=(l+r)>>1;
    if(l==r) return rt->ans.init(f[vt[l]],g[vt[r]],0);
    build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
    return rt->ans=merge_ans(rt->ch[0]->ans,rt->ch[1]->ans),0;
}
inline int push_up(segment* &rt)
{   return rt->ans=merge_ans(rt->ch[0]->ans,rt->ch[1]->ans),0;  }
inline int shows(segment* &rt)
{
    int l=rt->l,r=rt->r;
    if(l<r) shows(rt->ch[0]),shows(rt->ch[1]),push_up(rt);
    debug(l)sp,debug(r)sp,rt->ans.show();
    return 0;
}
int update(segment* &rt,int p,const answer &v)
{
    int l=rt->l,r=rt->r,mid;if(l==r) return rt->ans=v,0;
    return mid=(l+r)>>1,update(rt->ch[p>mid],p,v),push_up(rt);
}
int query(segment* &rt,int s,int t)
{
    int l=rt->l,r=rt->r,mid=(l+r)>>1;
    if(s<=l&&r<=t) return ans=merge_ans(ans,rt->ans),0;
    if(s<=mid) query(rt->ch[0],s,t);
    if(mid<t) query(rt->ch[1],s,t);
    return 0;
}
int update(int x,int v)
{
    static answer w;
    int c=0;for(int y=top[x];fa[y];y=top[fa[y]]) L[++c]=y;
    for(int i=c,y,z;i;i--) y=L[i],z=fa[y],ans.init(0,0,1),
        query(rt,in[y],in[bot[y]]),f[z]-=ans.g(),g[z]-=ans.ans();
    ans.init(f[x]+=v,g[x],0),update(rt,in[x],ans);
    for(int y=top[x],z=fa[y];z;z=fa[y=top[z]])
        ans.init(0,0,1),query(rt,in[y],in[bot[y]]),
        w.init(f[z]+=ans.g(),g[z]+=ans.ans(),0),update(rt,in[z],w);
    return 0;
}
int fir_dfs(int x,int f)
{
    fa[x]=f,sz[x]=1,son[x]=0;
    for(int i=h[x],y;i;i=e[i].pre)
        if((y=e[i].to)^fa[x])
        {
            fir_dfs(y,x),sz[x]+=sz[y];
            if(sz[y]>sz[son[x]]) son[x]=y;
        }
    return 0;
}
int sec_dfs(int x)
{
    vt[in[x]=++dfs_clock]=x;
    if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]);
    for(int i=h[x],y;i;i=e[i].pre)
        if((y=e[i].to)!=fa[x]&&e[i].to!=son[x])
            top[y]=y,sec_dfs(y),ans.init(0,0,1),query(rt,in[y],in[bot[y]]),f[x]+=ans.g(),g[x]+=ans.ans();
    return ans.init(f[x],g[x],0),update(rt,in[x],ans),bot[x]=(son[x]?bot[son[x]]:x);
}
int main()
{
    int n=inn(),q=inn(),x,v;build(rt,1,n);
    for(int i=1,u,v;i<n;i++)
        u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
    for(int i=1;i<=n;i++) f[i]=inn();
    fir_dfs(1,0),top[1]=1,sec_dfs(1);
//  for(int i=1;i<=n;i++) debug(i)sp,debug(fa[i])sp,debug(top[i])sp,debug(bot[i])sp,debug(in[i])sp,debug(vt[i])ln;
//  for(int i=1;i<=n;i++) debug(i)sp,debug(f[i])sp,debug(g[i])ln;
    while(q--)
        if(inn()) x=inn(),v=inn(),update(x,v);//update, a[x]+=v
        else ans.init(0,0,1),x=inn(),query(rt,in[x],in[bot[x]]),printf("%d\n",ans.ans());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81905651