CF 1110 D/E

CF 1110 D. Jongmah

题目大意:给你​\(n\)个瓷砖,每块瓷砖上有一个数字​\(a_i,(1\leq a_i\leq m)\)。你可以将三个有连续数字​\((比如3,4,5)\)的瓷砖或者三个数字相同​\((比如7,7,7)\)的瓷砖组成一个三元组。每个瓷砖只能用一次。问最多可以得到多少个三元组。​

比赛的时候好像全场A穿,然而并没有想到 (TAT

一开始想到\(DP\),但是​觉得状态数太大;于是想了奇奇怪怪的贪心,但是都能找到反例。

这道题的关键是要发现一个性质:同一位置上连续三个瓷砖匹配不会超过\(2\)个。因为如果凑够了\(3\)个就可以分别单独匹配了。这样一来状态数就少了:设\(f[i][j][k]\)表示\(DP\)到编号为\(i\)的瓷砖,以\(i-1\)结尾的连续匹配进行了\(j\)次,以\(i\)结尾的连续匹配进行了\(k\)次的最大三元组数。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define N 1000005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n,m;
int f[N][3][3],sum[N];
int main() {
	n=Get(),m=Get();
	int a;
	for(int i=1;i<=n;i++) {
		a=Get();
		sum[a]++;
	}
	memset(f,-0x3f,sizeof(f));
	f[2][0][0]=0;
	for(int i=2;i<m;i++) {
		for(int j=0;j<3;j++) {
			for(int k=0;k<3;k++) {
				if(f[i][j][k]<0) continue ;
				for(int q=0;q<3;q++) {
					if(sum[i+1]<q) break;
					if(sum[i]<k+q) break;
					if(sum[i-1]<j+k+q) break;
					f[i+1][k][q]=max(f[i+1][k][q],f[i][j][k]+(sum[i-1]-j-k-q)/3+q);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++)
			ans=max(ans,f[m][i][j]+(sum[m]-j)/3+(sum[m-1]-i-j)/3);
	cout<<ans;
	return 0;
}

总结:发现这种非一般套路的\(DP\)或者贪心题时要去发现题目的特殊性质,往往特殊性质是解题的关键。


CF 1110 E. Magic Stones

题目大意:给你两个长度为\(n\)的序列\(c\)\(t\)。你可以对\(c\)进行任意次操作,每次操作选取位置\(i(2\leq i\leq n-1)\),然后将\(c_i\)变成\(c_{i-1}+c_{i+1}-c_i\)

这题太神了,不过好像比赛时也被A穿了。

我们设\(d_i=c_{i+1}-c_i(1\leq i \leq n-1)\)。我们会发现,对\(c_i\)进行上述操作后,交换了\(d_{i-1}\)\(d_i\)

所以我们将两个数列的\(d\)数组求出来,排序后直接比较就行了。还有要判断\(c_1==t_1\)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define N 200005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n;
int c[N],t[N];
int dc[N],dt[N];
int main() {
	n=Get();
	for(int i=1;i<=n;i++) c[i]=Get();
	for(int i=1;i<=n;i++) t[i]=Get();
	for(int i=1;i<n;i++) dc[i]=c[i+1]-c[i];
	for(int i=1;i<n;i++) dt[i]=t[i+1]-t[i];
	if(c[1]!=t[1]) {cout<<"No";return 0;}
	sort(dc+1,dc+n);
	sort(dt+1,dt+n);
	for(int i=0;i<=n;i++) {
		if(dc[i]!=dt[i]) {cout<<"No";return 0;}
	}
	cout<<"Yes";
	return 0;
}

posted @ 2019-02-08 14:48  hec0411  阅读(214)  评论(0编辑  收藏  举报