首页 > 其他分享 >[CSP-S 2024] 染色

[CSP-S 2024] 染色

时间:2024-11-20 18:08:42浏览次数:1  
标签:last int 染色 sum cin 2024 cases now CSP

还是决定把这个题做了

考场上设计的状态,推了一个小时没推出来

下午推了一会,发现这是个刷表状态,填表没法做,转移无处下手

但是考 CSP 的时候我貌似并不知道什么叫刷表


设 \(f_{i,j,k}\) 表示当前到 \(i\),上一个填的红色位置在 \(j\),蓝色位置在 \(k\),暴力刷表转移是 3D/0D 的,需要排除不合法状态,\(j,k\) 里总有一个应该在 \(i-1\) 位置,否则状态就不合法

\(35pts\)

#include<bits/stdc++.h>
using namespace std;
int n;
int a[200001];
int f[102][101][101];
int ans=0;
int main(){
    ios::sync_with_stdio(false);
    int cases;cin>>cases;while(cases--){
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        ans=0;
        memset(f,0,sizeof f);
        for(int i=1;i<=n;++i){
            for(int j=0;j<i;++j){
                for(int k=0;k<i;++k){
                    if(j!=i-1 and k!=i-1) continue;
                    f[i+1][j][i]=max(f[i+1][j][i],f[i][j][k]+(a[k]==a[i]?a[i]:0));
                    f[i+1][i][k]=max(f[i+1][i][k],f[i][j][k]+(a[j]==a[i]?a[i]:0));
                    ans=max({ans,f[i+1][j][i],f[i+1][i][k]});
                }
            }
        }
        cout<<ans<<'\n';
    }
}

lbtl 说,既然都刷表了,为什么不写记搜呢,一语惊醒梦中人

在写记搜的同时也发现,由于 \(j,k\) 中一定会有一维是 \(i-1\),而另一维一定小于 \(i-1\),因此由 \(j,k\) 可以直接算出 \(i\)(\(i=\max(j,k)+1\)),\(i\) 可省去

记搜 \(50pts\)

#include<bits/stdc++.h>
using namespace std;
int n;
int a[10001];
int f[2001][2001];
int dfs(int now,int r,int b){
    if(now>n) return 0;
    if(f[r][b]!=-1) return f[r][b];
    return f[r][b]=max(dfs(now+1,now,b)+(a[now]==a[r]?a[now]:0),dfs(now+1,r,now)+(a[now]==a[b]?a[now]:0));
}
int main(){
    ios::sync_with_stdio(false);
    int cases;cin>>cases;while(cases--){
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        memset(f,-1,sizeof f);
        cout<<dfs(1,0,0)<<'\n';
    }
}

刷表法 \(50pts\)

#include<bits/stdc++.h>
using namespace std;
int n;
int a[200001];
int f[2001][2001];
int ans=0;
int main(){
    ios::sync_with_stdio(false);
    int cases;cin>>cases;while(cases--){
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        ans=0;
        memset(f,0,sizeof f);
        for(int j=0;j<n;++j){
            for(int k=0;k<n;++k){
                f[j][max(j,k)+1]=max(f[j][max(j,k)+1],f[j][k]+(a[k]==a[max(j,k)+1]?a[max(j,k)+1]:0));
                f[max(j,k)+1][k]=max(f[max(j,k)+1][k],f[j][k]+(a[j]==a[max(j,k)+1]?a[max(j,k)+1]:0));
                ans=max({ans,f[j][max(j,k)+1],f[max(j,k)+1][k]});
            }
        }
        cout<<ans<<'\n';
    }
}

写到这里已经 210 分了,考场上的我到底在干什么呢

这个做法空间压不下来,已经没前途了,想做正解还要另辟蹊径


返璞归真,设 \(f_i\) 表示考虑到第 \(i\) 位的答案

考虑从 \(f_{i-1}\) 转移到 \(f_i\),如果 \(f_i\) 完全没有贡献,那么应该有 \(f_i=f_{i-1}\)

如果 \(f_i\) 有贡献,考虑这个贡献一定是从最大的一个满足 \(j\lt i,a_j=a_i\) 的 \(j\) 转移过来的

证明:为了有贡献,\(j,i\) 中间的数必须全涂另一种颜色,强制涂同一种颜色贡献一定不优,因此需要尽可能减少 \(j,i\) 之间的点的个数

因此,将贡献拆成三段

  • \([1,j]\),由 \(f_j\) 可以知道
  • \([j+1,i-1]\),这是都涂同一种颜色的连续段
  • \(i\),刚才我们钦定 \(i\) 有贡献,这个贡献就是 \(a_i\)

这个东西需要处理细节,分别讨论 \(j,j+1\) 的颜色转移,题解区有一种更高明的分法

  • \([1,j+1]\)
  • \([j+2,i-1]\)
  • \(i\)

这么分是因为,由于离 \(i\) 最近的同值节点是 \(j\),因此 \(a_{j+1}\) 一定与 \(a_i,a_j\) 不相同,我们现在需要保证的是 \(j\) 涂的颜色与 \(i\) 一样,而 \(j+1\) 涂的与 \(i\) 不同,由于 \(j,j+1\) 涂相同的颜色完全没有收益,不存在这样的转移,因此 \(j,j+1\) 颜色一定不同,因此只需要钦定其中一个的颜色即可

现在复杂度瓶颈是第二个连续段,这一段可前缀和处理,因此上前缀和

复杂度线性

这题也有坑点

            // if(last[a[i]]) f[i]=max(f[i-1],f[last[a[i]]+1]+sum[i]-sum[last[a[i]]+1]+a[i]);
            // else f[i]=f[i-1];
            // last[a[i]]=i;

不能这么写是因为 last[a[i]]+1 有可能直接等于 i 了,因此需要提前更新 i 的值

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a[1000001];
int last[1000001];
int f[1000001];
int sum[1000001];
signed main(){
    ios::sync_with_stdio(false);
    int cases;cin>>cases;while(cases--){
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            last[a[i]]=0;
            sum[i]=sum[i-1]+(a[i]==a[i-1]?a[i]:0);
        }
        for(int i=1;i<=n;++i){
            f[i]=f[i-1];
            if(last[a[i]]) f[i]=max(f[i],f[last[a[i]]+1]+sum[i]-sum[last[a[i]]+1]+a[i]);
            last[a[i]]=i;
        }
        cout<<f[n]<<'\n';
    }
}

标签:last,int,染色,sum,cin,2024,cases,now,CSP
From: https://www.cnblogs.com/HaneDaCafe/p/18558481

相关文章

  • 实时多模态 AI 的 N 种新可能丨实时互动和大模型专场@RTE2024回顾
      在本届RTE2024大会上,来自产业界和学术界的多位专家深入探讨了实时互动和大模型技术的最新进展及其潜在应用。 西湖心辰联合创始人俞佳、声网AI算法工程师乔齐、MiniMax资深音频算法专家张博闻、商汤科技数字文娱解决方案负责人焦文奎以及面壁智能算法VP翟忠武等......
  • 2024.11.20总结
    本文于github博客同步更新。A:一个数可以被操作当且仅存在一列的顶部元素为它且存在一列的底部元素为它,初始扫一遍,将合法的元素以顶部所在列为关键字扔到小根堆里,每次找到最小的元素添加,然后检查将新露出来的元素是否存在匹配,若结束时未填完即为无解。B:要么在非环边上砍一刀,......
  • NOIP2024 前集训:NOIP2024加赛 6
    前言music《身骑白马》我爱谁跨不过从来也不觉得错自以为抓着痛就能往回忆里躲偏执相信着受诅咒的水晶球阻挡可能心动的理由而你却靠近了逼我们视线交错原地不动或向前走突然在意这分钟眼前荒沙弥漫了等候耳边传来孱弱的呼救追赶要我爱的不保留......
  • 《技术规划与技术平台开发管理赋能》公开课(2024年12月20-21日)
    【课程背景】随着国内外高科技领域的产品竞争越来越激烈,产品和解决方案的创新尤其是核心技术的自主创新已成为中国企业乃至整个中国商业社会转型的重要手段。公司的技术战略是基于战略高度对产品机遇和技术发展趋势的前瞻性认识,如果没有这种前瞻性的认识,产品、平台和技术就会在......
  • 2024源鲁杯部分wp
    pwn[Round1]giaopwnexp:#-*-coding:utf-8-*-frompwnimport*#fromLibcSearcherimport*#p=process("./pwn")p=remote("challenge.yuanloo.com",24519)elf=ELF("./pwn")#libc=ELF("./libc.so.6")context......
  • 哋它亢:2024datacon SEO
    哋它亢是一种新兴的技术,它来源于datacon2024的SEO赛题,作为其关键词给出。哋它亢作为一种新时代的朝阳产业,其结合了大数据与人工智能技术,通过添加大量机器学习算法,以实现高效的产出。哋它亢专栏文章列表:哋它亢:datacon2024SEO哋它亢:一种新兴SEO技术的datacon-1哋它亢:一种新......
  • 想要给文件加密?这8款实用的文件加密软件2024办公必备
    在当今信息化的社会中,数据安全越来越受到重视,无论是企业用户还是个人用户,都希望通过加密来保护文件的隐私和安全。以下为您整理了8款实用的文件加密软件,每款工具都功能强大,使用便捷,助您在2024年轻松保障数据安全。1.安秉网盾适合人群:企业用户安秉网盾文件加密是一款高效、......
  • 2024年想要加密文件?常用10款文件加密软件分享|企业办公必备!
    在数字化时代,数据安全是企业运营和个人隐私保护的重要一环。为了有效防止数据泄露,选择一款合适的文件加密软件至关重要。以下是2024年推荐的10款常用文件加密软件,这些软件各具特色,能够满足不同企业和个人的加密需求。1.安秉网盾安秉网盾是一款专注于企业级信息安全管理的工......
  • HZOI NOIP 2024 Round 24 T2 取石子 官方做法
    发现大多数的题解都是不同于官方题解的做法,这里我将介绍官方题解做法。Solution证明先手是否可以必胜的方法相差无几,为了方便后边行文,这里介绍我的思路:考虑各堆石子和为奇数的情况(以下简称为“奇状态”,另一种称为“偶状态”)一定先手必胜:两人一次取一个即可。考虑偶状态。可以发......
  • 2024年icpc南京区域赛随笔
    ​ 其实赛前也没对具体的赛站有什么了解。是教练把我们分配到这个赛站的。学长在赛前就一直在给我们灌输铜牌对于现在的形式来说已经没什么用了,银牌才有点含金量。所以赛前其实是抱着要拿银牌的心态来打这场南京的。​ 提前说一下结果吧:银牌。​ 赛时很快就切出了两道签到,一道字......