把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 P9911 [COCI 2023/2024 #2] Kuglice

传送门

题意

应该是显然的.

分析

首先,观察数据范围:1n3000,也就是说,时间复杂度应当在 O(n2) 左右。

其次,观察我们取球的顺序,是只能从左或右取,因此,我们每次留下的必然是连续的一段。

所以,我们显然可以采用区间 DP 来解决这道题。

确定状态:fi,j 表示现在取了剩下 ij,先手的最大得分。

考虑转移:由于我们是先后手易手的取数,所以我们当前的状态是从小 1 的区间的对立面转移过来,这里有两种方式,一种是直接记录对立面,另一种,我们可以记录区间能够取到的价值的总和,显然这个是和取法无关的。

#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int N = 3e3+5;
inline int read() {
int x;
scanf("%d",&x);
return x;
}
int n, m,a[N],qzh[N][N],tot[N][N],fr[N],en[N],f[N][N];
inline int val(int L,int R,int x) {
if(x) return L<=fr[a[R]]&&(en[a[R]]==R);
else return (fr[a[L]]==L)&&en[a[L]]<=R;
}
signed main() {
n=read();
memset(fr,0x3f,sizeof fr);
for(int i=1; i<=n; ++i) a[i]=read(),fr[a[i]]=min(fr[a[i]],i),en[a[i]]=i;
for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) qzh[i][j]=qzh[i-1][j]+(a[i]==j);
for(int i=1; i<=n; ++i) if(fr[i]<=en[i]) tot[fr[i]][en[i]]++;
for(int i=2; i<=n; ++i) {
for(int j=1; j+i-1<=n; ++j) {
int L=j,R=j+i-1;
tot[L][R]=tot[L][R]+tot[L+1][R]+tot[L][R-1]-tot[L+1][R-1];
}
}
for(int i=1; i<=n; ++i) {
for(int j=1; j+i-1<=n; ++j) {
int L=j,R=i+j-1;
f[L][R]=max(val(L,R,0)+tot[L+1][R]-f[L+1][R],tot[L][R-1]-f[L][R-1]+val(L,R,1));
}
}
cout<<f[1][n]<<":"<<tot[1][n]-f[1][n];
return 0;
}
posted @   djh0314  阅读(65)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示