NOIP模拟测试8「寿司」
考試時(shí)打的類似$n^2$暴力,然后炸了只有10分
后來驗(yàn)證我的算法偽了。
題解
?
顯然你有一種解法,假設(shè)你要在一個(gè)B點(diǎn)斷開將R分別移向最左 最右,這樣只用分別計(jì)算B點(diǎn)右面藍(lán)色數(shù)量左面藍(lán)色數(shù)量就得到了一個(gè)ans
這個(gè)題有一個(gè)很不顯然的結(jié)論,假設(shè)你要將R移向兩邊時(shí),序列唯一確定時(shí),設(shè)pos=(藍(lán)色數(shù)量+1)/2,在pos點(diǎn)將R移向左面,右面花費(fèi)最小(單調(diào)性)
因?yàn)檫@個(gè)序列是循環(huán)的所以我們只要枚舉B點(diǎn)斷開的位置就可以$n^2$求出最小的ans值
$n^2$顯然過不了1000000
現(xiàn)在我們思考$n^2$問題在哪,首先你每次重新計(jì)算一次ans額外花費(fèi)了時(shí)間,然后每次都枚舉斷點(diǎn)又花費(fèi)了時(shí)間
但實(shí)際上我們每次循環(huán)到下一個(gè)這個(gè)序列實(shí)際上變化很少,只是前面那個(gè)字母刪去,后面再加一個(gè)字母
實(shí)際對(duì)ans改變也很少
類似于莫隊(duì),對(duì)于ans+ - 我們可以得到另一個(gè)ans
那么我們可以計(jì)算出他的改變
首先我們可以得出每次循環(huán)到下一B,假設(shè)我們目前斷點(diǎn)不變,那么所有左邊R對(duì)ans造成貢獻(xiàn)都會(huì)減1,所有右邊R對(duì)ans造成貢獻(xiàn)都會(huì)加1
然后我們思考下一個(gè)斷點(diǎn),假設(shè)當(dāng)前斷點(diǎn)顯然就是下一個(gè)B
然后我們斷點(diǎn)移動(dòng)過程中我們發(fā)現(xiàn)有一些R從右面移動(dòng)到了左面,那么他要移動(dòng)貢獻(xiàn)也從右面blue數(shù)量改成了右面貢獻(xiàn),減去左面貢獻(xiàn)加上左面的貢獻(xiàn)即可
代碼
?
#include<bits/stdc++.h> #define ll long long #define A 2100000 using namespace std; ll t,len,n,ans,pos,zo,p; ll lb[A],rb[A],lr[A],rr[A]; char c[A]; int main() { // freopen("mkd.txt","r",stdin); // freopen("wa.txt","w",stdout);scanf("%lld",&t);while(t--){ans=0;zo=ans;lb[0]=rb[0]=lr[0]=rr[0]=0;scanf("%s",c+1);len=strlen(c+1);n=len;pos=-1;for(ll i=1;i<=len;i++){c[n+i]=c[i];}len*=2;rr[len+1]=rb[len+1]=0;for(ll i=1;i<=len;i++){lb[i]=lb[i-1],lr[i]=lr[i-1];if(c[i]=='B')lb[i]++;else lr[i]++;}for(ll i=len;i>=1;i--){rr[i]=rr[i+1],rb[i]=rb[i+1];if(c[i]=='B') rb[i]++;else rr[i]++;}pos=(lb[n]+1)/2; // printf("pos=%lld\n",pos);for(ll i=1;i<=n;i++){if(lb[i]==pos){p=i;for(ll j=n;j>i;j--){if(c[j]=='R')ans+=rb[j]-rb[n+1]; // printf("rr=%lld rr[n]=%lld\n",rr[j],rr[n+1]); }break;}else if(c[i]=='R')ans+=lb[i];} // printf("ans=%lld\n",ans);zo=ans;ll head=1,tail=n;while(head<=n){if(c[head]=='B'){ ans-=lr[p]-lr[head-1];//如果當(dāng)前為B將B向后移動(dòng)那么左邊所有R代價(jià)-1ans+=rr[p]-rr[tail+1];//如果當(dāng)前為B將B向后移動(dòng)那么右邊所有R代價(jià)+1while(c[++p]!='B'){//當(dāng)前指針應(yīng)當(dāng)指向下一個(gè)Bans+=lb[p]-lb[head];//如果R由左變?yōu)榱擞?#xff0c;那么代價(jià)從左邊變成右邊ans-=rb[p]-rb[tail+2];}}head++,tail++;zo=min(zo,ans);}cout<<zo<<endl;} } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/znsbc-13/p/11247211.html
總結(jié)
以上是生活随笔為你收集整理的NOIP模拟测试8「寿司」的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 房屋的买卖合同备案登记表一般什么时候可以
- 下一篇: NOIP模拟测试8「匹配·回家」