括號序列——我那令人智熄的操作
括號序列
題目描述:
輸入格式:
輸出格式:
樣例輸入:
6 0 0 1 1 0 1
樣例輸出:
3
提示:
解釋:
時間限制:1000ms
空間限制:128MByte
這題。。。以前做過題面很想的題目很多,但是這個題意不是很一樣。以前做的題面都是問前後括號數量是否匹配,這一個題目則是弄了一個特殊的計算方式來求由括號組成的字符串的值。於是,看到這個題目的一瞬間,模擬!
#include<bits/stdc++.h> using namespace std; int a[100000]={0},n,x,num=0,sum=0,ma=0,s=0,re=0,m=-1; int main(){ cin>>n; for (int i=1; i<=n; i++){ cin>>x; sum%=12345678910; if (a[1]==0) { s+=re+sum; re=0; s%=12345678910; sum=0; } if (x==0){ if (m!=-1 && a[1]!=0) m++; re+=sum; sum=0; ma=0; num++; a[num]=1; } else if (x==1){ if (ma==0 && a[num]==1){ if (m==-1) m=0; if (m!=-1 && m!=0) m--; sum+=1; a[num]=0; num--; ma=1; } else if (ma==1 && a[num]==1){ if (m!=0){ sum*=2; a[num]=0; num--; m--; } else { re+=sum; re*=2; sum=0; a[num]=0; num--; } } } } sum%=12345678910; s+=sum+re; s%=12345678910; cout<<s; return 0; }
這個還是我改了很久的代碼。到了後來還是只有三十分,剩下的點都WA掉了。然後到了最後還是這個分數。非常的無奈。
後來還是參考了一下大佬的程序,但是有點難理解,後來弄了一下子,最終還是搞懂了。總而言之,還是先貼一下大佬的程序把。
#include<bits/stdc++.h> using namespace std; const long long mod=12345678910; int n,x,cur,pre,cnt; long long s[100010],sum; int main(){ cin>>n; for(int i=0;i<n;i++){ scanf("%d",&x); if(x==0) cur++; if(x==1){ cur--; if(pre==0) s[cur]=(s[cur]+1)%mod; } pre=x; cnt=max(cnt,cur); } for(int i=cnt;i>=0;i--) s[i]=(s[i]+s[i+1]*2)%mod; cout<<s[0];return 0; }
然後用我神乎其技的畫技來展示一下大佬的程序,以及解釋一下樣例吧。
我們將樣例中的圖畫出來就是這個樣子的,雖然很醜,但是還是能夠勉強看一下的。前面貼出的代碼中最迷的就是這個s數組,s數組的下標代表的是括號的層數,如圖所示,然後,s[i]就代表在第i層時的分數。我們可以得出一個類似於動態規劃的狀態轉移方程的東西那就是s[i]=(s[i]+s[i-1]*2)%mod;其中要註意的一點就是s[1]代表的是第二層,而不是第一層,s[0]代表的才是第一層。然後接下來要解決的就是如何給每一個括號分層。這裏面我們完全不需要考慮運算中的乘的運算,因為我們可以放到外面去算,所以只需要考慮加的運算。
我們用cur這個變量來代表當前所能夠到達的層數,然後每次遇到左括號的時候就將cur++,來表示當前層數+1,然後遇到右括號時,需要考慮兩種情況:1.如果這個右括號之前是左括號,那就不要說什麽了cur--,然後將s[cur]++,表示在第cur層的時候分數+1。2.如果這個右括號之前還是右括號,這就表明與這個括號配對的另一個左括號並不是連續的,所以並不是使當前層數總值+1而是*2,就不能將s[cur]++了。然後在代碼中的cnt就是用來記錄一下最大值來減少在for中循環的次數。
最後我們用一個for循環來執行s[i]=(s[i]+s[i+1]*2)%mod這條語句,最後s[0]就是我們所要求的值了。
呵呵呵,模擬什麽的還是去屎把!!!這都是什麽操作!感覺自己就是來搞笑的,模擬都模擬不好,後面的點WA了這麽多,模擬的太失敗了。根本就是吔屎。仰天長嘯一句mmp!誒,令人智熄的操作*2.
括號序列——我那令人智熄的操作