• Codeforces Round #590 (Div. 3)补题



    要想上2000分,先刷几百道2000+的题再说 ———某神

    题目 E F
    赛时是否尝试 × ×
    tag math bitmask
    难度 2000 2400
    状态

    E

    待定


    F

    传送门
    第一次接触状态压缩dp的题。这道题转换问题的思路非常巧妙。
    原问题:
    已知: 一个字符串,可进行不超过一次操作
    操作限定: 选择某个子串,使其在原串中翻转
    目的:使原串的特征值最大
    串的特征值:串任意没有重复字符的子串,其包含字符的种类数

    问题的转换:
    首先选定一个子串a,之后再找到另一个子串b,使得a与b没有公共的字符,枚举a与b,就能求出最大的特征值(如果a与b相邻,则翻转b即可,反之,将a与b之间的区间与b连接在一起进行翻转,即可将b翻转到a的相邻位置)
    因为合法子串的长度不会超过20位(题目限定),所以每个合法子串我们都可以将其用一个二进制长度为20的整型表示
    与a 01互补的“串”不一定出现在原串中,所以对于每一个串,我们都要求出其最大的合法长度,以便我们最后计算答案

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i = (a);i>=(b);--i)
    #define fo(i,a,b) for(int i =(a);i<(b);++i)
    #define de(x) cout<<#x<<" = "<<x<<endl;
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a));
    #define ls(p) ((p)<<1)
    #define rs(p) (((p)<<1)|1)
    using namespace std;
    typedef long long ll;
    const int mn = 105;
    
    int main(){
    	string s;
    	cin >> s;
    	
    	vector <int> dp(1<<20);
    	for(int i = 0; i < int(s.size()); ++i){//  start char of substring
    		vector<bool> used(20);
    		int mask = 0;
    		for(int j = 0; i + j < int(s.size()); ++j){
    			if(used[s[i + j]-'a']) break; // current char has appear in the substring
    			used[s[i+j]-'a'] = true;        // update mask
    			mask |= 1<<(s[i+j]-'a');        // update dp hashtable
    			dp[mask] = __builtin_popcount(mask);
    		}
    	}
    	for(int mask = 0;mask < (1<<20);++mask){
    		for (int pos = 0; pos < 20;++pos) {
    			if((mask >> pos) & 1) {  
    				dp[mask] = max(dp[mask],dp[mask ^ (1 << pos)]);
    				//because mask ^ (1<<pos) < mask, dp[mask ^ (1 << pos)] have been iterated
       			}
    		}
    	}
    	
    	int ans = 0;
    	for(int mask = 0;mask < (1<<20);++mask) {
    		if(dp[mask] == __builtin_popcount(mask)){
    			/*
    				one interger's mask is absolutely less than or equal to itself
    				if mask unequals to itself ,that mean this substring do not appear
    				but it can show the complement string's max number
    			*/
    			int comp = ~mask & ((1 << 20)-1);
    			// get complement string's max number
    			ans = max(ans,dp[mask] + dp[comp]);
    		}
    	}
    	cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    BZOJ3832: [Poi2014]Rally(拓扑排序 堆)
    UVAlive6807 Túnel de Rata (最小生成树)
    UVAlive6800The Mountain of Gold?(负环)
    cf623A. Graph and String(二分图 构造)
    BZOJ4144: [AMPPZ2014]Petrol(最短路 最小生成树)
    cf605D. Board Game(BFS 树状数组 set)
    为什么要去创业?
    后缀数组练习题若干
    Android开发 之 我的jar包引用方法
    IBM-ETP 实训项目前一天
  • 原文地址:https://www.cnblogs.com/tea-egg/p/11626074.html
Copyright © 2020-2023  润新知