[CF585E]Marbles

Posted cnyali-tea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF585E]Marbles相关的知识,希望对你有一定的参考价值。

Description:

给定一个序列 \(a_i\) ,每次可以交换相邻两个元素,求使序列变成若干个极大连续段,每个极大连续段内部的值相同且任意两个极大连续段的值互不相同。

\(n\le 4\times 10^5, a_i\le 20\)

Solution:

由于值域很小,启发我们从值域入手,考虑每一种颜色。

\(cnt[i][j]\) 表示在只考虑颜色 \(i\)\(j\) 的情况下,把所以颜色 \(i\) 都移到所有颜色 \(j\) 的前面的步数,这个对每一个颜色用 \(\textvector\) 存下出现的位置(从小到大),用 \(\rm two\ pointers\) 扫一下即可求得 。

考虑状压每一种颜色,二进制下为1表示这个位的颜色已经被安排好了。

\(dp[S]\) 表示 \(S\) 的颜色已经安排好在序列的前面且两两不交的最小步数,那么转移就枚举一个不在 \(S\) 中的点 \(i\) ,把 \(i\) 放在考虑完的 \(S\) 的后面,那么产生的步数就是把 \(S\) 放在 \(i\) 的前面的步数,通过 \(cnt[][i]\) 可以求得。

Code:

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <fstream>

typedef long long LL;
typedef unsigned long long uLL;

#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define MP(x, y) std::make_pair(x, y)
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define GO cerr << "GO" << endl;

using namespace std;

inline void proc_status()

    ifstream t("/proc/self/status");
    cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;


template<class T> inline T read() 

    register T x(0);
    register char c;
    register int f(1);
    while (!isdigit(c = getchar())) if (c == '-') f = -1;
    while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
    return x * f;


template<typename T> inline bool chkmin(T &a, T b)  return a > b ? a = b, 1 : 0; 
template<typename T> inline bool chkmax(T &a, T b)  return a < b ? a = b, 1 : 0; 

const int maxN = 4e5;
const int maxM = 20;

int n;
vector<int> col[maxM + 1];
LL cnt[maxM + 1][maxM + 1];
LL dp[1 << maxM];

void Input()

    n = read<int>();
    for (int i = 1; i <= n; ++i)
    
        int x = read<int>();
        col[x].push_back(i);
    


void Init()

    for (int i = 1; i <= 20; ++i)
        for (int j = 1; j <= 20; ++j)
            if (i != j) 
            
                if (!col[i].size() || !col[j].size()) continue;
                int l = 0;
                for (int k = 0; k < SZ(col[i]); ++k)
                
                    while (true)
                    
                        if (l == SZ(col[j]) - 1 || col[j][l + 1] > col[i][k])
                            break;
                        l++;
                    
                    if (col[j][l] < col[i][k])
                        cnt[i][j] += l + 1;
                
            


void Solve()

    memset(dp, 0x3f, sizeof dp);

    dp[0] = 0;
    for (int S = 0; S < 1 << maxM; ++S)
    
        for (int i = 0; i < maxM; ++i)
            if (!(S >> i & 1))
            
                LL sum(0);
                for (int j = 0; j < maxM; ++j)
                    if (S >> j & 1)
                        sum += cnt[j + 1][i + 1];
                chkmin(dp[S | (1 << i)], dp[S] + sum);
            
    

    cout << dp[(1 << maxM) - 1] << endl;


int main() 

#ifndef ONLINE_JUDGE
    freopen("CF585E.in", "r", stdin);
    freopen("CF585E.out", "w", stdout);
#endif
    Input();
    Init();
    Solve();
    return 0;

以上是关于[CF585E]Marbles的主要内容,如果未能解决你的问题,请参考以下文章

rxjs-marbles 测试没有任何期望

Marbles(博弈SG函数)

lightoj-1050 - Marbles(dp)

UVA 10090 Marbles(扩展欧几里得)

超级账本Fabric区块链用弹珠游戏Marbles 部署

codeforces 1215 E Marbles-----状压DP