CF 1110 D. Jongmah
阿新 • • 發佈:2019-02-09
ostream cstring include type const ons == title 代碼
D. Jongmah
鏈接
題意:
一些數字,有兩種方式組成一個三元組,[x,x,x],[x,x+1,x+2],每個數字只能用一次,求最多組成多少三元組。
分析:
因為每三個[x,x+1,x+2]是可以拆成[x,x,x],[x+1,x+1,x+1],[x+2,x+2,x+2]的,所以可以認為對於以x開始的[x,x+1,x+2]最多有兩個。
於是可以dp[i][x][y]表示到第i個數字,存在x個[i-1,i,i+1],y個[i,i+1,i+2],最多組成多少個三元組(這些三元組的右端點在i以內,超出i三元組有x+y個,沒有記錄到裏面)
然後轉移的時候枚舉多少個[i+1,i+2,i+3]。
代碼:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inlineint read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f; } const int N = 1e6 + 10; LL f[N][3][3], a[N]; int main() { int n = read(), m = read(); for (int i = 1; i <= n; ++i) a[read()] ++; memset(f,-0x3f, sizeof(f)); f[0][0][0] = 0; for (int i = 1; i <= m; ++i) { for (int x = 0; x < 3; ++x) for (int y = 0; y < 3; ++y) for (int z = 0; z < 3; ++z) { if (a[i] < x + y + z) continue; f[i][x][y] = max(f[i][x][y], f[i - 1][z][x] + (a[i] - x - y - z) / 3 + z); } } cout << f[m][0][0]; return 0; }
CF 1110 D. Jongmah