AtCoder AGC030E Less Than 3
生活随笔
收集整理的這篇文章主要介紹了
AtCoder AGC030E Less Than 3
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接
https://atcoder.jp/contests/agc030/tasks/agc030_e
題解
又是個奇妙轉化題。。
當我們反轉一個位置時,該位置左右的數(shù)一定不一樣。那么假設我們把左邊是0右邊是1的連續(xù)兩個位置之間畫一道紅線,左邊是1右邊是0的連續(xù)兩個位置之間畫一道藍線,為了處理邊界問題我們假設首尾處都有無限多的紅線和藍線且整個序列滿足紅藍交替。那么我們的操作可以等價為把一條線向左或向右移動\(1\)個位置,且移動后滿足整個序列依然紅藍交替且任何兩條相鄰的線(除首尾外)間距為\(1\)或\(2\).
假設我們確定了兩個序列中所有線的對應關系,那么答案就是對應線位置差的絕對值之和。顯然可以構造出一種代價為此的方案,而由于任何相鄰兩個位置相差不超過\(2\), 一定不存在兩條相鄰的線,滿足一條線的目標位置在其之左,另一條線的目標位置在其之右。那么我們可以用“不動線”將這個序列分為若干段,每一段里全是向左或者全是向右,這顯然是可以達到的。
于是我們\(O(n)\)枚舉一下兩個串的位置對應關系,\(O(n)\)求一下總距離即可。
時間復雜度\(O(n^2)\).
代碼
#include<bits/stdc++.h> #define llong long long #define mkpr make_pair #define riterator reverse_iterator using namespace std;inline int read() {int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f; }const int N = 5000; char a[N+3],b[N+3]; int ta[N+3],tb[N+3]; int wa[3*N+7],wb[3*N+7]; int n,m1,m2;int get_ta(int x) {return x>m1?n:ta[x];} int get_tb(int x) {return x>m2?n:tb[x];}int main() {scanf("%d%s%s",&n,a+1,b+1);if(a[1]=='1') {ta[++m1] = 0;} for(int i=2; i<=n; i++) if(a[i]!=a[i-1]) {ta[++m1] = i-1;} if(a[n]=='1') {ta[++m1] = n;}if(b[1]=='1') {tb[++m2] = 0;} for(int i=2; i<=n; i++) if(b[i]!=b[i-1]) {tb[++m2] = i-1;} if(b[n]=='1') {tb[++m2] = n;}for(int i=m2+1; i<=m2+m1; i++) wa[i] = ta[i-m2];for(int i=1; i<=m2; i++) wa[i] = 0;for(int i=m2+m1+1; i<=m2+m1+m2; i++) wa[i] = n; // printf("wa: "); for(int i=1; i<=m2+m1+m2; i++) printf("%d ",wa[i]); puts("");int ans = 1e9;for(int i=0; i<=m1+m2; i+=2){for(int j=1; j<=m2; j++) {wb[i+j] = tb[j];}for(int j=1; j<=i; j++) {wb[j] = 0;}for(int j=i+m2+1; j<=m1+m2+m2; j++) {wb[j] = n;}int cur = 0;for(int j=1; j<=m1+m2+m2; j++) {cur += abs(wa[j]-wb[j]);}ans = min(ans,cur);}printf("%d\n",ans);return 0; }總結
以上是生活随笔為你收集整理的AtCoder AGC030E Less Than 3的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AtCoder AGC035D Add
- 下一篇: AtCoder AGC036E ABC