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
原文地址:https://www.cnblogs.com/lyttt/p/11718803.html