• 切糕 小白月赛45


    D-切糕_牛客小白月赛45 (nowcoder.com)

    今天把我做的一些括号序列的题都写一些

    C. Recover an RBS edu132 div2_三木森sam的博客-CSDN博客

    这个是cf里的题,多了个问号,问你是否可以通过更改问号,使其变成唯一序列

    这题的主要关注点在于唯一性,所以只需要遍历一遍即可,问号用到该用的地方上,然后最后看看是否满足最后的条件即可,不需要想其他的了

     

    还有一个这个题,有一点点偏思维。假设'('是1,‘)’是0

    然后这里注意是合法的括号序列或者是长度至少为2的回文,注意要是前缀,之前题目读假了所以错了。括号序列10,11(1开头的全部合法)。0...0(0开头的必须再遇到一个0可以构成一个回文)删掉就可以了。然后就按照这个来删就好

    代码贴一下:

    1. #pragma GCC optimize(1)
    2. #pragma GCC optimize(2)
    3. #pragma GCC optimize(3,"Ofast","inline")
    4. #define IOS ios::sync_with_stdio(false), cin.tie(0);
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. using namespace std;
    17. #define int long long
    18. typedef long long ll;
    19. typedef pair<int,int> PAII;
    20. const int N=2e6+10,M=5050,INF=0x3f3f3f3f,mod=1e9+7;
    21. map<int,int> mp;
    22. int a[N];
    23. signed main(){
    24. //IOS;
    25. int T;
    26. T=1;
    27. //cin>>T;
    28. while(T--)
    29. {
    30. int n;
    31. cin>>n;
    32. string ch;
    33. cin>>ch;
    34. string c;
    35. for(int i=0;isize();i++)
    36. {
    37. if(ch[i]=='(') c+='1';
    38. else if(ch[i]==')') c+='0';
    39. }
    40. int sum=0,s=0;
    41. for(int i=0;isize();)
    42. {
    43. if(i==c.size()-1) break;
    44. if(c[i]=='1')
    45. {
    46. i+=2;
    47. sum++;
    48. s+=2;
    49. continue;
    50. }
    51. if(c[i]=='0')
    52. {
    53. int pos=i+1;
    54. int cnt=0;
    55. while(possize()&&c[pos]=='1') pos++,cnt++;
    56. if(pos>=c.size()) break;
    57. cnt+=2;
    58. s+=cnt;
    59. sum++;
    60. i=pos+1;
    61. // cout<
    62. }
    63. }
    64. cout<" "<size()-s<<"\n";
    65. }
    66. return 0;
    67. }
    68. /*
    69. 0的话得碰到下一个0
    70. 1的话就2
    71. */

    然后开头的这个题

    题意就是给你给你一个括号串,遇到合法的串你可以选择切或者不切,问你有多少种切法

    合法:左右括号的数量要是一样的,任意前缀的左括号需要大于等于右括号

    这个题就是找到可切的地方,有cnt的地方,然后一个地方有两种选择(切或者不切),所以最后的答案是2^cnt。

    那怎么样判断一个位置是不是可切的呢,这里令左括号为1,右括号为-1,然后求前缀

    如果某一个前缀是负数,那整个序列都是不合法的所以输出-1

    (我刚开始做这题想的是如果负数的怎么办,我以为负数的部分是可以量化的,也就是可以切出来的,但是其实不能,就相当于多了一个右括号,那它是没办法匹配的)

    如果在最后的s[n]的位置不等于0了,就相当于也是切不出的,这题你要知道,能切出来的前提是在序列合法的情况下切出的,切只是相当于把一个合法序列切成若干的合法序列而已

    然后什么时候可以开始切呢,就是在合法的时候可以切,因为s[i]>0的时候是左括号>右括号,如果等于0,那么刚好,并且可以匹配

    代码贴上:

    1. #pragma GCC optimize(1)
    2. #pragma GCC optimize(2)
    3. #pragma GCC optimize(3,"Ofast","inline")
    4. #define IOS ios::sync_with_stdio(false), cin.tie(0);
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. using namespace std;
    17. #define int long long
    18. typedef long long ll;
    19. typedef pair<int,int> PAII;
    20. const int N=2e6+10,M=5050,INF=1e18,mod=1e9+7;
    21. int a[N],s[N];
    22. signed main(){
    23. //IOS;
    24. int T;
    25. T=1;
    26. //cin>>T;
    27. while(T--)
    28. {
    29. string ch;
    30. cin>>ch;
    31. ch=" "+ch;
    32. int n=0;
    33. for(int i=0;isize();i++)
    34. {
    35. if(ch[i]=='(') a[++n]=1;
    36. else if(ch[i]==')') a[++n]=-1;
    37. }
    38. int f=1,cnt=0;
    39. for(int i=1;i<=n;i++)
    40. {
    41. s[i]=s[i-1]+a[i];
    42. if(s[i]<0) f=0;
    43. if(s[i]==0&&i!=n) cnt++;
    44. // cout<
    45. }
    46. if(s[n]!=0) f=0;
    47. if(f==0)
    48. {
    49. cout<<"-1\n";
    50. continue;
    51. }
    52. int res=1;
    53. for(int i=1;i<=cnt;i++) res=(res*2)%mod;
    54. cout<"\n";
    55. }
    56. return 0;
    57. }
    58. /*
    59. */

  • 相关阅读:
    vue3 中的根据某些特定的文字来筛选数组数据
    【服务器数据恢复】EXT3文件系统下raid数据恢复案例
    孙哥Spring源码第26集
    【C++】 C++入门和基础
    树莓派 Pico RP2040 MicroPython 编程 - 软件安装及设置
    离散数学 --- 图论基础 --- 无向图的连通性和有向图的连通性
    算法训练营day48,动态规划16
    【C++ Primer Plus学习记录】递增运算符(++)和递减运算符(--)
    docker ,k8s 以及 k8s 和 docker的关系
    【数据结构与算法】多路查找树的介绍(B树、B+树、B*树)
  • 原文地址:https://blog.csdn.net/m0_63305704/article/details/126725343