专栏文章
CF2053F Earnest Matrix Complement 题解
CF2053F题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @miqmq0pd
- 此快照首次捕获于
- 2025/12/04 07:19 3 个月前
- 此快照最后确认于
- 2025/12/04 07:19 3 个月前
题意
给定一个 的矩阵 ,每个数在 间,其中有一些数待填。
定义该矩阵的权值为:
其中 表示 在第 行出现的次数。
求填完数后该矩阵权值最大值。
。
做法
首先发现每行只会填一种数,否则替换成上下两行出现次数总和最多的数一定不劣。
先把已知的数的贡献算出来,然后只需要考虑填的数造成的影响。
不难得到朴素 dp 方式:
设 表示考虑前 行,第 行填的数是 的方案数。
不难发现 只会从 或 中的最大值转移过来,设这个最大值是 ,第 行的待填数有 个,那么可以得到转移式:
(这里的 表示在输入给出的已知数中, 在第 行出现的次数)
式子可能有点长,我们拆成两步看:
发现第一步转移对所有的 都一样,可以直接全局加,全局取 。
第二步总转移次数是上下两行出现数字个数之和,也就是一共 次单点加。
所以只要维护一个能支持全局加,全局取 ,单点加,求全局 的东西就可以了,可以用线段树之类的东西实现,不过打个全局标记就可以了,这样每次就是 的,具体可以看代码。
代码
一个能支持全局加,全局取 ,单点加,求全局 的东西:
CPPnamespace A{
ll addtag,maxtag;
ll a[600001];
ll mx;
void clear()
{
for(int i=1;i<=k;++i)a[i]=0;
addtag=maxtag=mx=0;
}
void alladd(cll x)
{
addtag+=x;
maxtag+=x;
}
void allmax(cll x)
{
maxtag=max(maxtag,x);
}
void add(cint x,cll y)
{
a[x]=max(a[x],maxtag-addtag);
a[x]+=y;
mx=max(mx,a[x]);
}
ll ask()
{
return max(maxtag,mx+addtag);
}
}
dp 部分:
CPPfor(int i=1;i<=n;++i)
{
cll lstans=A::ask();
A::alladd(1ll*emp[i]*emp[i-1]);
A::allmax(lstans);
for(int x:a[i-1])
{
if(x==-1)continue;
A::add(x,emp[i]);
}
if(i<n)
{
for(int x:a[i+1])
{
if(x==-1)continue;
A::add(x,emp[i]);
}
}
}
提交记录:
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...