• CF The World Is Just a Programming Task (Easy Version)【分析·思维】


    题目传送门

    题意:

    给定一个括号序列,随意交换两个位置的括号之后,问有多少个不同长度的圈。关于圈的定义大概就是:将括号序列的后$k$个数放到括号序列的最前面,就是长度为$k$的圈。(看了好久题意emmm...)

    分析:

    首先,我们可以$n^2$暴力枚举交换的位置,然后再看有多少个圈。

    然后,对于括号序列的正确性判断,有一个非常巧妙的方法,(只适用于只有一种括号,既有小括号,又有中括号是不得行的):

    给$"("$赋值为1,$")"$赋值为-1,计算这个序列的前缀和,只要保证前缀和的每一位都大于等于0,并且最后一位刚好等于0,这个序列就是正确的括号序列。

    然后再枚举一个$k$,也就是圈的长度。要判断这个$k$成不成立,也就是要保证变换之后的前缀和每一个都要大于等于0。

    根据数学课上老师的传授,这是一个恒成立问题,我们只需要让最小的那个数在变换之后大于等于0就可以了。

    用一个前缀最小值和后缀最小值,$m1[k]$表示$1~k$的最小值,$m2[k]$表示$k~n$的最小值,在变换之后,如果$m1[k]+(a[n]-a[i])>=0$&&$m2[k+1]-a[i]>=0$,那么就符合条件。

     

     1 #include<iostream>
     2 #include<string>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<map>
     6 #include<algorithm>
     7 using namespace std;
     8 #define N 505
     9 #define ll long long
    10 #define INF 0x3f3f3f3f
    11 int n,ans,l,r;
    12 char s[N];
    13 int a[N]/*前缀和*/,min1[N]/*前缀最小值*/,min2[N]/*后缀最小值*/;
    14 void swp(int i,int j)
    15 {
    16     char tmp=s[i];
    17     s[i]=s[j],s[j]=tmp;
    18 }
    19 int f()
    20 {
    21     int res=0;
    22     for(int i=1;i<=n;i++)
    23     {
    24         if(s[i]=='(') a[i]=a[i-1]+1;
    25         if(s[i]==')') a[i]=a[i-1]-1;
    26         min1[i]=min2[i]=INF; 
    27         min1[i]=min(min1[i-1],a[i]);
    28     }
    29     for(int i=n;i>=1;i--)
    30         min2[i]=min(min2[i+1],a[i]);
    31     if(min1[n]>=0&&a[n]==0) res++;//不进行轮换就已经是正确的序列 
    32     for(int i=1;i<n;i++)//从i和i+1之间断开
    33         if(min2[i+1]-a[i]>=0&&min1[i]+(a[n]-a[i])>=0&&a[n]==0)
    34             res++; 
    35     return res;
    36     //程序一开始的时候就判断了a[n]!=0的情况 所以这里不写其实也可以 
    37 }
    38 int main()
    39 {
    40     scanf("%d",&n);
    41     scanf("%s",s+1);
    42     int cnt1=0,cnt2=0;
    43     for(int i=1;i<=n;i++)
    44     {
    45         if(s[i]=='(') cnt1++;
    46         else cnt2++;
    47     }
    48     if(cnt1!=cnt2)
    49     {
    50         puts("0
    1 1");
    51         return 0;
    52     }
    53     ans=f(),l=1,r=1;
    54     for(int i=1;i<=n;i++)
    55         for(int j=i+1;j<=n;j++)
    56         {
    57             if(s[i]==s[j]) continue;
    58             swp(i,j);
    59             int res=f();
    60             if(ans<res) ans=res,l=i,r=j;
    61             swp(i,j);
    62         }
    63     printf("%d
    %d %d
    ",ans,l,r);
    64     return 0;
    65 }
    Code
  • 相关阅读:
    C++中两种获取UUID的方法(编程)
    在python中发送自定义消息
    lib,dll的位置
    GetWindowText
    SuspendThread and ResumeThread
    创建线程检查按钮的状态
    C++检测句柄的权限
    POJ2186 强联通
    POJ2186 强联通
    POJ 1201 差分约束(集合最小元素个数)
  • 原文地址:https://www.cnblogs.com/lyttt/p/11718803.html
Copyright © 2020-2023  润新知