[luogu 5024] 保卫王国

luogu 5024(保卫王国)

Problem Here

Solution

这大概是一篇重复累赘的blog吧。

最小覆盖集=全集-最大独立集

强制取或不取,可以通过将权值修改成inf或者-inf

然后就用动态dp的套路就行了

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define MN 100005
#define inf 1000000005
int n,m,v[MN];
struct edge{int to,nex;}e[MN<<1];
int hr[MN],en;
std::set<int> mp[MN];
inline void ins(int f,int t)
{
    mp[f].insert(t);
    mp[t].insert(f);
    e[++en]=(edge){t,hr[f]};hr[f]=en;
    e[++en]=(edge){f,hr[t]};hr[t]=en;
}
int mx[MN],siz[MN],top[MN],fa[MN];
void dfs1(int x,int f)
{
    siz[x]=1;fa[x]=f;register int i;
    for(i=hr[x];i;i=e[i].nex)if(f^e[i].to)
    {
        dfs1(e[i].to,x);siz[x]+=siz[e[i].to];
        if(siz[e[i].to]>siz[mx[x]]) mx[x]=e[i].to;
    }
}
void dfs2(int x,int f,int tp)
{
    top[x]=tp;if(mx[x]) dfs2(mx[x],x,tp);
    register int i;
    for(i=hr[x];i;i=e[i].nex)if((e[i].to^f)&&(e[i].to^mx[x])) dfs2(e[i].to,x,e[i].to);
}
struct matrix
{
    ll a[2][2];
    matrix(){memset(a,0,sizeof a);}
    matrix operator * (const matrix &b) const
    {
        register matrix c;register int i,j,k;
        for(i=0;i<2;++i)for(j=0;j<2;j++)for(k=0;k<2;++k)
        c.a[i][j]=max(c.a[i][j],b.a[i][k]+a[k][j]);
        return c;
    }
}t[MN<<2],Ans;
ll g[MN][2],f[MN][2],sum;
int pos[MN],id[MN],dind,st[MN];
void init(int x,int F)
{
    register int i;g[x][1]=(ll)v[x];
    for(i=hr[x];i;i=e[i].nex)
    if((e[i].to^F)&&(e[i].to^mx[x]))
    {
        init(e[i].to,x);
        g[x][0]+=max(f[e[i].to][0],f[e[i].to][1]);
        g[x][1]+=f[e[i].to][0];
    }
    f[x][0]=g[x][0];f[x][1]=g[x][1];
    if(mx[x])
    {
        init(mx[x],x);
        f[x][0]+=max(f[mx[x]][0],f[mx[x]][1]);
        f[x][1]+=f[mx[x]][0];
    }
    pos[x]=++dind;id[dind]=x;
    if(st[top[x]]==0) st[top[x]]=dind;
}
#define mid ((l+r)>>1)
void build(int k,int l,int r)
{
    if(l==r)
    {
        t[k].a[0][0]=t[k].a[0][1]=g[id[l]][0];
        t[k].a[1][0]=g[id[l]][1];t[k].a[1][1]=0ll;
        return;
    }
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    t[k]=t[k<<1]*t[k<<1|1];
}
void Modify(int k,int l,int r,int x)
{
    if(l==r)
    {
        t[k].a[0][0]=t[k].a[0][1]=g[id[l]][0];
        t[k].a[1][0]=g[id[l]][1];t[k].a[1][1]=0ll;
        return;
    }
    if(x<=mid) Modify(k<<1,l,mid,x);
    else Modify(k<<1|1,mid+1,r,x);
    t[k]=t[k<<1]*t[k<<1|1];
}
matrix query(int k,int l,int r,int a,int b)
{
    if(l==a&&r==b) return t[k];
    if(b<=mid) return query(k<<1,l,mid,a,b);
    if(a>mid) return query(k<<1|1,mid+1,r,a,b);
    return query(k<<1,l,mid,a,mid)*query(k<<1|1,mid+1,r,mid+1,b);
}
ll Que()
{
    Ans=query(1,1,n,st[1],pos[1]);
    return max(Ans.a[0][0],Ans.a[1][0]);
}
inline void change(int x,ll add)
{
    g[x][1]+=add;
    while(x!=0){
        Modify(1,1,n,pos[x]);
        matrix tmp=query(1,1,n,st[top[x]],pos[top[x]]);
        ll f0=tmp.a[0][0],f1=tmp.a[1][0];
        if(top[x]!=1){
            g[fa[top[x]]][1]+=f0-f[top[x]][0];
            g[fa[top[x]]][0]+=max(f1,f0)-max(f[top[x]][0],f[top[x]][1]);
        }
        f[top[x]][0]=f0;f[top[x]][1]=f1;
        x=fa[top[x]];
    }
}
int main()
{
    register char ch[5];
    n=read(),m=read();scanf("%s",ch+1);
    register int i,j,a,b;
    for(i=1;i<=n;i++) v[i]=read(),sum+=1ll*v[i];
    for(i=1;i<n;i++) j=read(),ins(j,read());
    dfs1(1,0);dfs2(1,0,1);init(1,0);build(1,1,n);
    while(m--)
    {
        i=read();j=read();a=read(),b=read();
        if(j==0&&b==0&&mp[i].count(a))
        {
            puts("-1");
            continue;
        }
        change(i,(j==0?1:-1)*inf);
        change(a,(b==0?1:-1)*inf);
        printf("%lld\n",sum-Que()+1ll*(j==0?1:0)*inf+1ll*(b==0?1:0)*inf);
        change(i,(j==0?-1:1)*inf);
        change(a,(b==0?-1:1)*inf);
    }
    return 0;
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

原文地址:https://www.cnblogs.com/PaperCloud/p/10000428.html

时间: 2024-10-13 10:24:51

[luogu 5024] 保卫王国的相关文章

【noip2018】【luogu5024】保卫王国

题目描述 Z 国有nn座城市,n - 1n−1条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻扎军队.驻扎军队需要满足如下几个条件: 一座城市可以驻扎一支军队,也可以不驻扎军队. 由道路直接连接的两座城市中至少要有一座城市驻扎军队. 在城市里驻扎军队会产生花费,在编号为i的城市中驻扎军队的花费是p_ipi?. 小 Z 很快就规划出了一种驻扎军队的方案,使总花费最小.但是国王又给小 Z 提出 了mm个要求,每个要求规定了其中两

P5024 保卫王国

——————————————————————————————————————————————- 考前练习打打部分分 设置权值这个方法需要记住 ———————————————————————————————————————————————————— PT:44 ———— #include<bits/stdc++.h> using namespace std; const int inf=1000000000; char ch[5]; int n,m,head[101000],ne,a,b,c,d

LuoguP5024 保卫王国(动态DP,树形DP,矩阵加速,LCT)

最小权覆盖集 = 全集 - 最大权独立集 强制取点.不取点可以使用把权值改成正无穷或负无穷实现 接下来就是经典的"动态最大权独立集"了 O(nlogn). 这不是我说的,是immortalCO大佬说的 于是我调了一万年极值,终在\(\frac{LLONG\_MAX}{3}\)时\(11s\)卡过... 知道最小权覆盖集 = 全集 - 最大权独立集,就是模板\(DDP\)了 #include <cstdio> #include <iostream> #includ

P5024 保卫王国[倍增+dp]

窝当然不会ddp啦,要写这题当然是考虑优化裸dp啦,但是这题非常麻烦,于是变成了黑题. 首先,这个是没有上司的舞会模型,求图的带权最大独立集. 不考虑国王的限制条件,有 \[ dp[x][0]+=dp[y][1]\dp[x][1]+=min(dp[y][1],dp[y][0]) \] 现在考虑限制条件,如果对每一个限制条件都做一次dp,复杂度达到\(O(n^2)\),无法承受. 显然,对于这些限制条件,每一次的变动不会影响其它大多数的状态. 对于一个限制条件,我们分开考虑,先考虑只对一个城市进行

【考试】10.2

1>保卫王国 一棵树,有点权, 树上一条边上要求至少一个点被选, 现在有好多个询问,要求一个点被选,或者没有被选 求问每个询问的最小代价 (1)很明显的树形dp, 简单的暴力,对每次询问,求一次dp,用dfs 复杂度O(nm) 前11个点,44分 (2)优化dp 因为m优化不得,离线也没什么用, 所以,估计最终的复杂度应该是O(mlogn) 再画一棵树,发现每次影响的其实只有x到y这一段中的dp, (当然相邻节点有一点...影响) 我们把要更新的部分分成三部分: 设两个点为u,v,t=LCA(u

noip历年试题

noip2018 铺设道路 货币系统 赛道修建 一眼贪心.随便实现. 旅行 环套树枚举删除环上哪条边. 填数游戏 找规律,这谁会啊. 保卫王国 动态Dp,去问这位神仙. noip2017 小凯的疑惑 就是数论结论题,当然也可以找规律. 时间复杂度 原理都懂,大模拟. 逛公园 SPFA还没死.jpg 奶酪 宝藏 状压Dp. 列队 我太懒了直接Splay模拟. noip2016 玩具谜题 天天爱跑步 考虑一条链怎么做(随便做),然后树上同理. 换教室 组合数问题 蚯蚓 拿两个队列来归并. 愤怒的小鸟

我爱OI(来自一个年老但是毫无成就的IOer的退役感言)

某盆终于退役了... 这可能是本博客的最后一篇文章了吧... 如果不,那就还有两个方向: 1.自己闲得无聊学学算法 2.当成自己的随笔博客不知道该干些什么了.AFO了. 然后呢?该扯点什么了?? 额说到这,想起来我们也学了4年OI了吧 从第一年的暑假,78人,坐在实验的大机房里,每人带一瓶冰块, 到第二年的50人,分布在沈老师的五个班里, 再到仅剩的20人,分布在一中二中, 渐渐的,只剩下9人依旧奋战在一线, 一次意外,我们的团队又少了一个人——bk201. 一路经历了多少? 四次集训,分布全国

模版 动态 dp

模版 动态 dp 终于来写这个东西了.. LG 模版:给定 n 个点的数,点有点权, $ m $ 次修改点权,求修改完后这个树的最大独立集大小. 我们先来考虑朴素的最大独立集的 dp \[ dp[u][0] = \sum_v max\{dp[v][1],dp[v][0]\}\\dp[u][1] = val[u] + \sum_v dp[v][0] \] 现在我们就拥有了一个 $ O(nm) $ 的做法,但是明显它不优秀. 既然支持修改,我们可以考虑树剖(或者LCT),现在树被我们剖成了重链和轻链

京东笔试编程题:采购单+保卫方案

采购单时间限制:C/C++语言 1000MS:其他语言 3000MS内存限制:C/C++语言 65536KB:其他语言 589824KB题目描述:过年啦!小B高兴的不行了,她收到了很多红包,可以实现好多的愿望呢.小B可是对商店货架上心仪的货物红眼好久了,只因囊中羞涩作罢,这次她可是要大大的shopping一番.小B想去购物时,总是习惯性的把要买的东西列在一个购买清单上,每个物品单独列一行(即便要买多个某种物品),这次也不例外.小B早早的来到了商店,由于她太激动,以至于她到达商店的时候,服务员还没