首页 > 其他分享 >CF1598F RBS 题解

CF1598F RBS 题解

时间:2022-11-15 16:33:28浏览次数:67  
标签:pre CF1598F const 前缀 int 题解 RBS MAXM dp

题意

给 \(n\) 个串,求将这 \(n\) 个串以任意顺序接起来的最大的是合法括号序列的前缀数。

分析

\(n\) 很小,考虑状压 dp。

有一个很典的转化是将 看成 \(+1\),将 ) 看成 \(-1\),于是问题就转化成求将 \(n\) 个只含 \(+1,-1\) 的序列任意接起来的最大合法前缀数,合法前缀的定义为处处前缀和非负,且该前缀总和为 \(0\)。

发现对于选中几个串安排好,无论前面是怎么排的都不对后面有影响,因为排好部分的总和一定。\(dp_{S,0/1}\) 表示已经在前面安排好的字符串状态为 \(S\) ,存在前缀和小于 \(0\) / 不存在时的最大合法括号序列数。设前面排好的总和为 \(pre\),对于每一个串预处理一下前缀 \(\min\),二分找到第一个 \(+pre<0\) 的位置,再二分求出在该位置前的 \(=-pre\) 的前缀和数 \(cnt\),直接转移即可。

核心代码

const int MAXN=21;
const int MAXM=4e5+7;
const int _=4e5;
int n,dp[1<<MAXN][2],sum[1<<MAXN],pr[MAXN][MAXM],mn[MAXN][MAXM];string s[MAXN];
vector<int>vec[MAXN][MAXM+MAXM];
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n;int i,j,mask,tmp;for(i=0;i<n;i++) cin>>s[i];mem(dp,0xcf);dp[0][1]=0;
    for(i=0;i<n;i++){
        pr[i][0]=(s[i][0]=='('?1:-1);mn[i][0]=-pr[i][0];
        vec[i][pr[i][0]+_].emplace_back(0);
        for(j=1;j<s[i].size();j++){
            pr[i][j]=pr[i][j-1]+(s[i][j]=='('?1:-1);
            mn[i][j]=-qmin(-mn[i][j-1],pr[i][j]);
            vec[i][pr[i][j]+_].emplace_back(j);
        }
    }for(mask=1;mask<(1<<n);mask++) 
        for(i=0;i<n;i++) if(mask&(1<<i)) sum[mask]+=pr[i][s[i].size()-1];
    for(mask=1;mask<(1<<n);mask++){
        for(i=0;i<n;i++){
            if(!(mask&(1<<i))) continue;tmp=mask^(1<<i);
            int pre=sum[tmp];bool flag=true;if(pre-mn[i][s[i].size()-1]<0) flag=false;
            int p=upper_bound(mn[i],mn[i]+s[i].size(),pre)-mn[i],cnt=0;
            if(vec[i][-pre+_].empty()||vec[i][-pre+_].front()>=p) cnt=0;
            else if(vec[i][-pre+_].back()<p) cnt=vec[i][-pre+_].size();
            else cnt=lower_bound(vec[i][-pre+_].begin(),vec[i][-pre+_].end(),p)-vec[i][-pre+_].begin();
            if(flag){
                dp[mask][1]=qmax(dp[mask][1],dp[tmp][1]+cnt);
                dp[mask][0]=qmax(dp[mask][0],dp[tmp][0]);
            }else dp[mask][0]=qmax(dp[mask][0],dp[tmp][0],dp[tmp][1]+cnt);
        }
    }printf("%d\n",qmax(dp[(1<<n)-1][0],dp[(1<<n)-1][1]));
    return 0;
}

record

标签:pre,CF1598F,const,前缀,int,题解,RBS,MAXM,dp
From: https://www.cnblogs.com/lxy-2022/p/CF1598F-Solution.html

相关文章

  • CF 1743 题解
    比赛链接:https://codeforces.com/contest/1743题解:AB水题//bySkyRainWind#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include......
  • week3题解
    1.寄包柜   看到题目最容易想到开二位数组但数据量过大,因此需要map#include<bits/stdc++.h>usingnamespacestd;map<int,map<int,int>>a;这里开了一个map......
  • el-date-picker 等 点击无反应不回显问题解决
    参考链接:https://blog.csdn.net/QQ2856639881/article/details/116918081?spm=1001.2101.3001.6661.1&depth_1-utm_relevant_index=1最近在做一个动态表单回显。数据嵌套......
  • vue项目中eslint报“Missing space before function parentheses”的问题解决
    原文链接:https://blog.csdn.net/u011523953/article/details/1067718681、问题原因:使用eslint时,严格模式下,报错Missingspacebeforefunctionparentheses(函数括号前缺少......
  • 【题解】CF1748D ConstructOR
    前言这道题十分诈骗,比赛的时候以为是根据二进制除法原理,解同余方程,然后考试时候就没做出来QAQ。这篇题解是构造解法,至于官方题解是啥我也不知道,看这官方题解的性质十分诡......
  • P8816 [CSP-J 2022] 上升点列 题解
    题目传送门:luoguP8816[CSP-J2022]上升点列这是一道简单的dp题。定义到达指两点的曼哈顿距离是\(1\)。我们考虑设状态\(f(i,j)\)表示考虑结尾是第\(i\)个点,增......
  • P6406 [COCI2014-2015#2] Norma 题解
    前言洛谷上很多大佬都写的CDQ分治的解法。但看了某篇大佬的线段树解法,受益匪浅,于是决定写一篇题解来记录一下这种解法。前置知识:单调栈,线段树题目通道题目描述给......
  • CF1743F Intersection and Union 题解
    更好体验线段的贡献不好统计,考虑统计每一个点在不同情况中的被覆盖次数,那么每个点的被覆盖次数总和即为答案。设\(f_{i,j,0/1}\)表示\(i\)点在扫描到线段\(j\)时是......
  • LG5283 [十二省联考 2019] 异或粽子 题解
    口胡一个异或经典问题LG5283[十二省联考2019]异或粽子给定一个长为\(n\)的序列,序列一段子区间\([l,r]\)的值为\([l,r]\)范围内所有数异或起来的值。现在求出前......
  • 题解 HDU4035 【Maze】
    postedon2022-08-1712:33:51|under题解|sourceproblemhttps://vjudge.net/problem/HDU-4035SHY在一棵树上随机游走,从根节点出发,每次有\(k_u\)的几率回到根节......