zoukankan      html  css  js  c++  java
  • [CF585E]Marbles

    Description:

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

    (nle 4 imes 10^5, a_ile 20)

    Solution:

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

    (cnt[i][j]) 表示在只考虑颜色 (i)(j) 的情况下,把所以颜色 (i) 都移到所有颜色 (j) 的前面的步数,这个对每一个颜色用 ( ext{vector}) 存下出现的位置(从小到大),用 ({ m 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;
    }
    
  • 相关阅读:
    DBHelper
    jsTree使用
    爬虫系列之Scrapy框架
    Mongodb安装
    爬虫系列之mongodb
    爬虫学习目录
    爬虫之selenium模块
    爬虫简介与requests模块
    爬虫数据解析的三方式
    线程相关
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/11530714.html
Copyright © 2011-2022 走看看