CF1110D Jongmah

经典题。

Link

题意

你手中有 n 张牌。每张牌上都写着一个介于 1m 之间的整数。要赢得游戏,需要组成一定数量的三元组。每个三元组由三张牌组成,这样写在牌上的数字要么全部相同,要么连续。例如, 7,7,712,13,14 都是有效的三连牌,但 2,2,32,4,6 则不是。你只能用手中的牌组成三元组。每张牌最多只能组成一个三元组。
为了确定你离胜利有多近,您需要知道你手中的牌最多可以组成多少个三元组。

Solution

注意到,对于 i 这张牌(牌上数字为 i),它选择 (i,i+1,i+2)(i,i,i) 的数量是受 i1,i2 影响的,所以我们首先会有一个暴力 DP:fi,j,k 表示当前选择到第 i 种牌,i 选择了 j(i,i+1,i+2)i1 选择了 k(i1,i,i+1)

转移显然为 fi,j,k=maxl=0cnti2fi1,k,l+cntijkl3+j
其中 cnti 表示牌上数字为 i 的牌的张数。

注意到这样做的时间复杂度是 O(nm3),完全不能通过。

有一个很好的性质是如果我们组成了 c(c3) 个形如 (i,i+1,i+2) 的三元组,可以将其转换为 c3 个形如 (i,i,i) 的三元组,这么做一定不劣。
那么对于上面转移中的 j,k,l,只需要枚举 [0,2] 即可。

然后就做完了。时间复杂度 O(33n)

#include <bits/stdc++.h>

// #define int long long
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
#define rep(i,l,r) for (int i = (int)(l); i <= (int)(r); ++ i )
#define rep1(i,l,r) for (int i = (int)(l); i >= (int)(r); -- i )
#define il inline
#define fst first
#define snd second
#define ptc putchar
#define Yes ptc('Y'),ptc('e'),ptc('s'),puts("")
#define No ptc('N'),ptc('o'),puts("")
#define YES ptc('Y'),ptc('E'),ptc('S'),puts("")
#define NO ptc('N'),ptc('O'),puts("")
#define vi vector<int>
#define pb emplace_back
#define sz(x) (int)(x.size())
#define all(x) x.begin(),x.end()
#define me(a,x) memset(a,x,sizeof a)
#define get(x) ((x - 1) / len + 1)
#define debug() puts("------------")

using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<ll,ll> PLL;
namespace szhqwq {
    template<class T> il void read(T &x) {
        x = 0; T f = 1; char ch = getchar();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
        x *= f;
    }
    template<class T,class... Args> il void read(T &x,Args &...x_) { read(x); read(x_...); }
    template<class T> il void print(T x) {
        if (x < 0) ptc('-'), x = -x; 
        if (x > 9) print(x / 10); ptc(x % 10 + '0');
    }
    template<class T,class T_> il void write(T x,T_ ch) { print(x); ptc(ch); }
    template<class T,class T_> il void chmax(T &x,T_ y) { x = x < (T)y ? (T)y : x; }
    template<class T,class T_> il void chmin(T &x,T_ y) { x = x > (T)y ? (T)y : x; }
    template<class T,class T_,class T__> il T qmi(T a,T_ b,T__ p) {
        T res = 1; while (b) {
            if (b & 1) res = res * a % p;
            a = a * a % p; b >>= 1;
        } return res;
    }
    template<class T> il T gcd(T a,T b) { if (!b) return a; return gcd(b,a % b); }
    template<class T,class T_> il void exgcd(T a, T b, T_ &x, T_ &y) {
        if (b == 0) { x = 1; y = 0; return; }
        exgcd(b,a % b,y,x); y -= a / b * x; return ;
    }
    template<class T,class T_> il T getinv(T x,T_ p) { 
        T inv,y; exgcd(x,(T)p,inv,y);
        inv = (inv + p) % p; return inv;
    }
} using namespace szhqwq;
const int N = 1e6 + 10,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
const db eps = 1e-6;
int n,m,a[N],cnt[N],f[N][3][3];

il void solve() {
    //------------code------------
    read(n,m); rep(i,1,n) read(a[i]),++ cnt[a[i]];
    rep(i,1,m) 
        rep(j,0,2) rep(k,0,2) rep(l,0,2) 
            if (cnt[i] >= j + k + l && cnt[i - 1] >= k + l && (i == 1 || cnt[i - 2] >= l))
                chmax(f[i][j][k],f[i - 1][k][l] + (cnt[i] - j - k - l) / 3 + j);
    int ret = f[m][0][0];
    write(ret,'\n');
    return ;
}

il void init() {
    return ;
}

signed main() {
    // init();
    int _ = 1;
    // read(_);
    while (_ -- ) solve();
    return 0;
}
posted @   songszh  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示