NOIP2018 Day2 T3 保卫王国 - 动态dp - 树剖 - 线段树

直接裸上动态dp即可,因为某些不知道的原因NOIP能过,别的地方不开O2都过不了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define gc getchar()
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
char Type[10];
const int N=100010;
struct edges{
    int to,pre;
}e[N<<1];int p[N],qa[N],qb[N],qx[N],qy[N],h[N],etop;
inline int add_edge(int u,int v)
{
    return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
namespace subtask1{
    const int N=2010;const lint INF=100000000000ll;
    int mst[N],mstx[N];lint f[N][2];
    int dfs(int x,int fa=0)
    {
        f[x][0]=0,f[x][1]=p[x];
        for(int i=h[x],y;i;i=e[i].pre)
            if((y=e[i].to)^fa)
            {
                dfs(y,x);
                f[x][0]+=f[y][1];
                f[x][1]+=min(f[y][0],f[y][1]);
            }
        f[x][0]=min(f[x][0],INF),
        f[x][1]=min(f[x][1],INF);
        if(mst[x]) f[x][mstx[x]^1]=INF;
        return 0;
    }
    inline int brute_force_nm(int n,int m)
    {
        rep(i,1,m)
        {
            int a=qa[i],b=qb[i],x=qx[i],y=qy[i];
            mst[a]=mst[b]=1,mstx[a]=x,mstx[b]=y;
            dfs(1);
            lint Ans=min(f[1][0],f[1][1]);
            if(Ans<INF) printf("%lld\n",Ans);
            else printf("-1\n");
            mst[a]=mst[b]=0;
        }
        return n-n+0;
    }
}
namespace subtask_std{
    const lint INF=100000000000;
    struct node{
        int ept;lint w[3][3];
        inline node operator+(const node &n)const
        {
            node ans;rep(i,0,1) rep(j,0,1) ans.w[i][j]=INF;
            if(ept) ans=n;if(n.ept) ans=*this;ans.ept=0;
            if(ept||n.ept) return ans;
            rep(i,0,1) rep(j,0,1) rep(k,0,1) rep(t,0,1)
                if(k+t>=1) ans.w[i][j]=min(ans.w[i][j],w[i][k]+n.w[t][j]);
            return ans;
        }
        inline node operator+=(const node &n)
        {	return (*this)=(*this)+n;	}
        inline lint f()const { return min(w[1][0],w[1][1]); }
        inline lint g()const { return min(w[0][0],w[0][1]); }
        inline lint ans()const { return min(f(),g()); }
    }ans;
    struct segment{
        int l,r;
        segment *ch[2];
        node v;
    }*rt;
    lint g[N],f[N],fs[N],gs[N];int tms[N],dfc;
    int in[N],out[N],top[N],bot[N],d[N],fa[N],sz[N],son[N];
    inline int push_up(segment* &rt)
    {
        return rt->v=rt->ch[0]->v+rt->ch[1]->v,0;
    }
    int build(segment* &rt,int l,int r)
    {
        rt=new segment,rt->l=l,rt->r=r;
        if(l==r)
        {
            rt->v.w[0][1]=rt->v.w[1][0]=INF,
            rt->v.w[0][0]=g[tms[l]],rt->v.w[1][1]=f[tms[l]];
            return 0;
        }
        int mid=(l+r)>>1;
        build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
        return push_up(rt);
    }
    int update(segment* &rt,int p,lint f,lint g)
    {
        int l=rt->l,r=rt->r,mid=(l+r)>>1;
        if(l==r)
        {
            rt->v.w[0][1]=rt->v.w[1][0]=INF,
            rt->v.w[0][0]=g,rt->v.w[1][1]=f;
            return 0;
        }
        update(rt->ch[p>mid],p,f,g);return 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+=rt->v,0;
        if(s<=mid) query(rt->ch[0],s,t);
        if(mid<t) query(rt->ch[1],s,t);
        return 0;
    }
    int fir_dfs(int x)
    {
        d[x]=d[fa[x]]+1;
        for(int i=h[x],y;i;i=e[i].pre)
            if((y=e[i].to)^fa[x])
            {
                fa[y]=x,fir_dfs(y),sz[x]+=sz[y];
                if(sz[y]>sz[son[x]]) son[x]=y;
            }
        return ++sz[x];
    }
    int sec_dfs(int x)
    {
        in[x]=++dfc,tms[dfc]=x;
        if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]),bot[x]=son[x][bot];
        else bot[x]=x;
        f[x]=p[x],g[x]=0;
        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);
                f[x]+=min(gs[y],fs[y]);
                g[x]+=fs[y];
            }
        if(son[x]) fs[x]=f[x]+min(fs[son[x]],gs[son[x]]),gs[x]=g[x]+fs[son[x]];
        else fs[x]=f[x],gs[x]=g[x];
        out[x]=dfc;return 0;
    }
    inline int qry(int x) { ans.ept=1,query(rt,in[x],in[bot[x]]);return 0; }
    int lst[N];
    inline int upd(int x,int v)
    {
        int cnt=0;
        for(int y=top[x],z=fa[y];z;y=top[z],z=fa[y])
            lst[++cnt]=y;
        for(int i=cnt,y,z;i;i--)
            y=lst[i],z=fa[y],qry(y),
            update(rt,in[z],f[z]-=ans.ans(),g[z]-=ans.f());
        if(v) update(rt,in[x],f[x],g[x]=INF);
        else update(rt,in[x],f[x]=INF,g[x]);
        for(int i=1,y,z;i<=cnt;i++)
            y=lst[i],z=fa[y],qry(y),
            update(rt,in[z],f[z]+=ans.ans(),g[z]+=ans.f());
        return 0;
    }
    lint tf[N],tg[N];
    inline int back(int x)
    {
        update(rt,in[x],f[x]=tf[x],g[x]=tg[x]);
        for(int y=top[x],z=fa[y];z;y=top[z],z=fa[y])
            update(rt,in[z],f[z]=tf[z],g[z]=tg[z]);
        return 0;
    }
    inline int acceptable_solution(int n,int m)
    {
        fir_dfs(1),top[1]=1,sec_dfs(1);
        rep(i,1,n) tf[i]=f[i],tg[i]=g[i];
        build(rt,1,n);
        rep(i,1,m)
        {
            upd(qa[i],qx[i]),
            upd(qb[i],qy[i]);
            qry(1);
            if(ans.ans()<INF) printf("%lld\n",ans.ans());
            else printf("-1\n");
            back(qa[i]),back(qb[i]);
        }
        return 0;
    }
}
int main()
{
    int n=inn(),m=inn(),x,y;scanf("%s",Type);
    rep(i,1,n) p[i]=inn();
    rep(i,1,n-1) x=inn(),y=inn(),add_edge(x,y),add_edge(y,x);
    rep(i,1,m) qa[i]=inn(),qx[i]=inn(),qb[i]=inn(),qy[i]=inn();
    if(n<=2000&&m<=2000) return subtask1::brute_force_nm(n,m);
    return subtask_std::acceptable_solution(n,m);
    return 0;
}

猜你喜欢

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