[CC-SEINC]Sereja and Subsegment Increasings
阿新 • • 發佈:2018-08-18
執行 多少 -i 相等 int() etc line 序列 segment ,\(D_l+=4,D_r-=4\)。
[CC-SEINC]Sereja and Subsegment Increasings
題目大意:
有長度為\(n(n\le10^5)\)的序列\(A\)和\(B\)。
在一次操作中,可以選擇一個區間增加\(1\)。
求讓\(A\)和\(B\)在模\(4\)意義下相等,至少要對\(A\)執行多少次操作。
思路:
對\(A,B\)對應作差,\(C_i=B_i-A_i\)。
求\(C\)的查分\(D_i=C_i-C_{i+1}\)。
如果不考慮模\(4\),答案即為\(\sum\max(D_i,0)\)。
而模\(4\)相當於可以對\(C\)區間加\(4\),對應到\(D\)上就是對於區間\((l,r]\)
考慮怎樣選擇區間能夠使答案更優。
對於區間\((l,r]\),考慮以下情況:
- \(D_l=2,D_r=-3\),會使答案\(-1\);
- \(D_l=3,D_r=-2\),會使答案\(-1\);
- \(D_l=3,D_r=-3\),會使答案\(-2\)。
而其余情況都不會使答案更優。
因此可以線性掃一遍,記錄\(2,3\)出現的次數,將當前點作為右端點時擇優更新答案即可。
時間復雜度\(\mathcal O(n)\)。
源代碼:
#include<cstdio> #include<cctype> #include<algorithm> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } const int N=1e5+1; int a[N]; int main() { for(register int T=getint();T;T--) { const int n=getint(); for(register int i=1;i<=n;i++) a[i]=getint(); for(register int i=1;i<=n;i++) { a[i]=(getint()-a[i]+4)%4; } int ans=a[n],cnt2=0,cnt3=0; for(register int i=1;i<n;i++) { a[i]-=a[i+1]; ans+=std::max(0,a[i]); } for(register int i=1;i<=n;i++) { if(a[i]==2) cnt2++; if(a[i]==3) cnt3++; if(a[i]==-2) { if(cnt3) { cnt2++; cnt3--; ans--; } } if(a[i]==-3) { if(cnt3) { cnt3--; ans-=2; } else if(cnt2) { cnt2--; ans--; } } } printf("%d\n",ans); } return 0; }
[CC-SEINC]Sereja and Subsegment Increasings