• 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;
    }
    
    
  • 相关阅读:
    windows-如何免费让电脑自带的家庭中文版升级成专业版且不需要重装
    服务器管理-windows服务器如果让服务器自动定时重启
    International Olympiad In Informatics 2009 August 8 – 15, Plovdiv, Bulgaria Contest Day 1
    USACO 2008 FEB Eating Together
    POJ 2823 Sliding Window 滑动窗口 单调队列 Monotone Queue
    1st Junior Balkan Olympiad in Informatics Boats 船 DP
    USACO 2009 FEB Fair Shuttle 庙会班车 贪心
    USACO 2007 NOV Sunscreen 防晒霜 贪心
    JN 刷墙 过程DP
    Luogu
  • 原文地址:https://www.cnblogs.com/tea-egg/p/11626074.html
Copyright © 2020-2023  润新知