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 '\n'
#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;
}

原文地址:https://www.cnblogs.com/tea-egg/p/11626074.html

时间: 2024-08-27 21:33:50

Codeforces Round #590 (Div. 3)补题的相关文章

Codeforces Round #634 (Div. 3) 补题

A. Candies and Two Sisters 签到题,直接输出即可 代码 #include<bits/stdc++.h> #define INF 0x3f3f3f3f typedef long long ll; using namespace std; inline void read(int &p) { p=0;int flag=1;char c=getchar(); while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();} w

Codeforces Round #419 (Div. 1) 补题 CF 815 A-E

A-C传送门 D Karen and Cards 技巧性很强的一道二分优化题 题意很简单 给定n个三元组,和三个维度的上限,问存在多少三元组,使得对于给定的n个三元组中的每一个,必有两个维度严格小于. 首先我们根据一个维度(c维)对n个三元组排序,然后枚举答案在这个维度的取值. 此时序列被分成了两个部分,前半部分 满足所有c大于等于i 后半部分满足所有c严格小于i(即已有一个维度小于) 通过累计,我们知道此时前半部a维的最大值ma和b维的最大值mb. 显然可能存在的三元组答案,必然首先满足a维和

Codeforces Round #617 (Div. 3) 补题记录

1296A - Array with Odd Sum 题意:可以改变数组中的一个数的值成另外一个数组中的数,问能不能使数组的和是个奇数 思路:签到,如果本来数组的和就是个奇数,那就OK 如果不是,就需要把数组中其中一个奇(偶)数改成偶(奇)数,相当于加一减一 所以测一下这个数组如果有个奇数并且还有个偶数就行 #include <cstdio> #include <iostream> #include <map> #include <set> #include

Codeforces Round #627 (Div. 3) 补题

CF1324A Yet Another Tetris Problem 长度为n的数组a中有一组数,可以任意使其中一项+2,问能否使a中所有项的值相同. 感觉div.3的题目更多地在考简化问题的能力--比如原题目以俄罗斯方块作背景,让我想到的是能不能消除所有方块,导致代码很难写.但如果像上述一样简化题意,方向就很明确了:只要判断是否所有数均为偶数/均为奇数即可. CF1324A-代码 #include<cstdio> #include<iostream> #include<cs

Codeforces Round #257 (Div. 2) E题:Jzzhu and Apples 模拟

E. Jzzhu and Apples time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has picked n apples from his big apple tree. All the apples are numbered from 1 to n. Now he wants to sell them to

Codeforces Round #243 (Div. 1) A题

http://codeforces.com/contest/425/problem/A 题目链接: 然后拿出这道题目是很多人不会分析题目,被题目吓坏了,其中包括我自己,想出复杂度,一下就出了啊!真是弱! 直接暴力求出矩阵数值,然后枚举每一个[I,J];再O[N]判断,分配好在[I,J]区间的数和之内的数,再排序下SOLO了 CODE:#include <cstdio> #include <cstring>#include <queue>#include <vect

Codeforces Round #590 (Div. 3) Editorial

Codeforces Round #590 (Div. 3) Editorial 题目链接 官方题解 不要因为走得太远,就忘记为什么出发! Problem A 题目大意:商店有n件商品,每件商品有不同的价格,找出一个最小的可能值price,使得price * n >= sum,sum指的是原来商品价格的总和. 知识点:模拟 思路:求出sum/n向上取整即可,有两种方法.一是使用ceil()函数,但注意ceil()返回的是向上取整后的浮点数,所以要进行强制类型转换:二是直接向下取整,然后用if语句

Codeforces Round #396 (Div. 2) D题Mahmoud and a Dictionary(并查集)解题报告

Mahmoud wants to write a new dictionary that contains n words and relations between them. There are two types of relations: synonymy (i. e. the two words mean the same) and antonymy (i. e. the two words mean the opposite). From time to time he discov

Codeforces Round #590 (Div. 3)(e、f待补

https://codeforces.com/contest/1234/problem/A A. Equalize Prices Again 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int n,a; 6 int t; 7 cin>>t; 8 ll sum = 0,ans; 9 while(t--){ 10 cin>>n;sum = 0