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\n1 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\n%d %d\n",ans,l,r);
64     return 0;
65 }
Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM