首页 > 其他分享 >[BZOJ3037] 创世纪 题解

[BZOJ3037] 创世纪 题解

时间:2024-04-20 10:22:40浏览次数:22  
标签:cnt 环上 int 题解 BZOJ3037 lp cases 创世纪 dp

基环内向树上 dp,不过在这里提供给一种非典型做法。

考虑将环上的每一条边都断开,这样就会形成多棵树,先在这些树上进行树形 \(dp\)。设 \(dp_{i,0/1}\) 表示不选/选 \(i\) 时,\(i\) 子树内的最大选点数。明显方程为:

\[\begin{cases}dp_{u,0}=\sum\limits_{v\in uson}\max(dp_{v,0},dp_{v,1})\\ \\dp_{u,1}=[\sum\limits_{v\in uson}[dp_{v,0}\ge dp_{v,1}]>0]?dp_{u,0}:dp_{u,0}-\min\limits_{v\in uson}(dp_{v,1}-dp_{v,0})\end{cases} \]

接下来,我们开始在环上找答案。考虑断环为链。设 \(f_{i,0/1,0/1}\) 表示在环上的第 \(i\) 个点,选不选,第 \(cnt\) 个点选不选,\(lp_i\) 表示环上第 \(i\) 个点的编号。则转移方程为:

\[\begin{cases} f_{i,0,0/1}=\max(f_{i-1,0,0/1},f_{i-1,1,0/1})+dp_{lp_i,0}\\ f_{i,1,0/1}=\max(f_{i-1,0,0/1}+dp_{lp_i,0}+1,f_{i-1,1,0/1}+dp_{lp_i,1}) \end{cases} \]

时间复杂度瓶颈为并查集(不知道并查集干什么用的,详见上一道题我写的题解),时间复杂度 \(O(n\log n)\)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
int n,m,h[N],to[N],nxt[N];
int cnt,lp[N],v[N],fh[N],ans;
int dp[N][2],f[N][2][2],t[N];
void add(int x,int y){
    to[++m]=y;
    nxt[m]=h[x];
    h[x]=m;
}void init(){
    for(int i=1;i<=n;i++)
        fh[i]=i;
}int find
(int x){
    if(fh[x]==x) return x;
    return fh[x]=find(fh[x]);
}void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y) return;
    fh[y]=x;
}void dp_(int x){
    int f=1,mn=1e9;
    for(int i=h[x];i;i=nxt[i]){
        if(v[to[i]]) continue;
        int y=to[i];dp_(y);
        dp[x][0]+=max(dp[y][0],dp[y][1]);
        if(dp[y][0]>=dp[y][1]) f=0;
        else mn=min(mn,dp[y][1]-dp[y][0]);
    }dp[x][1]=dp[x][0]+1;
    if(f) dp[x][1]-=mn;
}void solve(int rt){
    int x=rt,y=t[rt];cnt=0;
    lp[++cnt]=y;v[y]=1;
    while(y!=x){
        lp[++cnt]=t[y];
        v[t[y]]=1;y=t[y];
    }for(int i=1;i<=cnt;i++) dp_(lp[i]);
    f[0][0][1]=f[0][1][0]=-1e9;
    for(int i=1;i<=cnt;i++){
        f[i][0][0]=max(f[i-1][0][0],f[i-1][1][0])+dp[lp[i]][0];
        f[i][1][0]=max(f[i-1][0][0]+dp[lp[i]][0]+1,f[i-1][1][0]+dp[lp[i]][1]);
        f[i][0][1]=max(f[i-1][0][1],f[i-1][1][1])+dp[lp[i]][0];
        f[i][1][1]=max(f[i-1][0][1]+dp[lp[i]][0]+1,f[i-1][1][1]+dp[lp[i]][1]);
    }ans+=max(f[cnt][0][0],f[cnt][1][1]);
}int main(){
    scanf("%d",&n);init();
    for(int i=1;i<=n;i++){
        cin>>t[i];
        add(t[i],i);
        unite(t[i],i);
    }for(int i=1;i<=n;i++)
        if(find(i)==i) solve(i);
    printf("%d",ans);
    return 0;
}//Kaká

标签:cnt,环上,int,题解,BZOJ3037,lp,cases,创世纪,dp
From: https://www.cnblogs.com/chang-an-22-lyh/p/18147287/bzoj3037_chuangshiji_tj

相关文章

  • [题解]ABC209F Deforestation
    ABC209FDeforestation首先我们可以思考\(a_i\)和\(a_{i+1}\)先砍哪棵花费少。可以看出,当\(a[i]<a[i+1]\)时,先砍\(a[i+1]\),反之亦然。所以这个题转化成了:给定\(n-1\)个关系,分别表示\(n\)个值中相邻两个的大小关系,问满足这些关系的序列个数。与AtcoderEducationalDPContest......
  • φ(* ̄0 ̄)3337. poj1845 sumdiv题解
    遇到数论题就要推式子!提供最美丽的latex\[a^b=p_1^{a_1*b}*p_2^{a_2*b}*p_3^{a_3*b}......*p_n^{a_n*b}\\那么他的因数之和为:\\({p_1}^0+{p_1}^1+...+{p_1}^{a_1*b})\\*({p_2}^0+{p_2}^1+...+{p_2}^{a_2*b})\\...\\*({p_n}^0+{p_n}^1+...+{p_n}^{a_n*b})\\=>利用等......
  • 「NOIP2012」同余方程 题解!!
    嗨嗨嗨!又是我想写这道题,我们就需要掌握:拓展欧几里得顾名思义,它就是欧几里得算法(人话:辗转相除法)的proMax版本别告诉我你不会辗转相除法拓展欧几里得的作用是求对于方程\[a*x+b*y=gcd(a,b)\]解出x,y的值。让我们一步步分析!贴个辗转相除板子先:voidojld(inta,intb){ i......
  • poj3696 The Luckiest number 题解
    很容易想到,\(n\)个8可以转换为\((10^{n+1}-1)/9*8\)容易你个集贸啊,xzz推10分钟我推了一个上午顺便膜拜xzz然后就是推式子了。。。(悲\[(10^{n+1}-1)/9*8\equiv0\pmodh\\=>{10^{n+1}*8-8\above1pt9}\equiv0\pmodh\\=>10^{n+1}*8-8\equiv0\pmod{9h}\\=>10^{n+1}*8\e......
  • P321. [NOI2002]荒岛野人Savage题解?!!!
    还是我容易(☚xzz说的)想出,x年后i号野人的位置为:\((C_i+P_i*x)\modm\)我们只要让任意方程:\((C_i+P_i*x)\modm=(C_j+P_j*x)\modm\)解小于\(L_i\)或小于\(L_j\)即可推式子!\[(C_i+P_i*x)≡(C_j+P_j*x)\(mod~m)\\⇿x*(P_i-P_j)+y*m=C_j-C_i\]然后就是拓展欧几里得模板了。......
  • 题解:CSP-S2020] 函数调用
    题解:CSP-S2020]函数调用一句话题意:给定一个有初始值的序列,支持如下三种操作:1、单点加2、全局乘3、递归某些操作1、2、3求最终的序列。标签:topsort,动态规划,转化贡献统计(集中贡献),主客翻转关于topsort:部分分里的树结构基本上直接暗示了正解要使用topsort,而且本来函......
  • CF1713F Lost Array 题解
    题目链接点击打开链接题目解法很牛的题!!!先考虑\((0,i)\)对\((j,n)\)的贡献,因为是异或,所以只要考虑奇偶性问题可以抽象成一条路径对应\(a_i\)的贡献,所以是否有\(a_i\)的贡献看\(\binom{n-i+j-1}{j-1}\)的奇偶性根据\(kummer\)定理,这个组合数是奇数当且仅当\(n-i+......
  • [题解][洛谷P1412] 经营与开发
    题目描述给定n,k,c,w,然后输入n组数据,数据分为两种:1ai:可以选择获得aiw的价值,但w会变成w(1-0.01*k)2bi:可以选择损失biw的价值,但w会变成w(1+0.01*c)求可获得的最大价值是多少。题解看到这个题,我的第一思路是求后缀和,然后让新得到的系数乘后缀和判断是否进行操作。但问题在于,对于......
  • 高斯消元学习笔记——P304题解
    如果你觉得这篇太啰嗦问题[SDOI2006]线性方程组题目描述已知\(n\)元线性一次方程组。\[\begin{cases}a_{1,1}x_1+a_{1,2}x_2+\cdots+a_{1,n}x_n=b_1\\a_{2,1}x_1+a_{2,2}x_2+\cdots+a_{2,n}x_n=b_2\\\cdots\\a_{n,1}x_1+a_{n,2}x......
  • ABC349F题解
    思想看到LCM想到质因数分解。首先,我们先把\(M\)质因数分解了,根号复杂度刚好1e8级别。然后我们发现一个很显然的性质:如果一个数不是\(M\)的因数那他肯定没用。所以此处我们就把不是因数地踢掉。我们惊奇地发现因为\(M\)的质因数分解最多\(13\)个不同的质数,然后我......