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

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

传送门

题意

应该是显然的.

分析

首先,观察数据范围:\(1\le n\le 3000\),也就是说,时间复杂度应当在 \(O(n^2)\) 左右。

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

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

确定状态:\(f_{i,j}\) 表示现在取了剩下 \(i\sim j\),先手的最大得分。

考虑转移:由于我们是先后手易手的取数,所以我们当前的状态是从小 \(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 @ 2024-01-24 15:01  djh0314  阅读(148)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end