AtCoder AGC001D Arrays and Palindrome (构造)
補一下原來做過的AtCoder思維題的題解
題目鏈接: https://atcoder.jp/contests/agc001/tasks/agc001_d
先特判一些小的情況。
原題就相當于每個回文串對稱的位置連邊,要求圖聯通。一個長度為\(k\)的回文串,會連\([\frac{k}{2}]\)(中括號下取整)條邊。假設所有回文串(包括\(a\)和\(b\))的長度為\(l_i\), 則\(\sum l_i=2n, \sum[\frac{l_i}{2}]\ge 2n-1\), 可得\(\sum (l_i\mod 2)\le 2\), 奇數長度的回文串不超過\(2\)個。
考慮一種連邊方式: 比如\([1,9]\)是回文串,\([1,8]\)是回文串,那么\(a_9=a_1=a_8=a_2=a_7=a_3=a_6=a_4=a_5\), 很容易得到\(a_1\)至\(a_9\)全相等。假設我們再令\([10,17]\)是回文串,\([9,16]\)是回文串,那么\(a_9=a_{16}=a_{11}=a_{14}=a_{13}=a_{12}=a_{15}=a_{10}=a_{17}\), 則\(a_1\)至\(a_{17}\)全相等。但是如果我們令\([10,18]\)和\([9,17]\),而不是\([10,17]\)和\([9,16]\), 那么將得到\(a_9=a_{17}=a_{11}=a_{15}=a_{13}\), 再無法連通。意思就是如果奇數的放到開頭或者結尾沒有問題,但是如果放到中間會有問題。那么既然奇數長度的回文串不超過\(2\)個那么把它們換到開頭結尾即可。
代碼
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std;const int N = 2e5; int a[N+3]; int n,m;int main() {scanf("%d%d",&n,&m); int cnt = 0;for(int i=1; i<=m; i++) {scanf("%d",&a[i]); cnt += (a[i]&1);}if(m==1){if(a[1]==1) printf("1\n1\n1\n");else printf("%d\n2\n%d %d\n",a[1],1,a[1]-1);return 0;}else if(m==2){if(a[1]==1 && a[2]==1) {printf("1 1\n1\n2\n");}else if(a[1]==1) {printf("1 %d\n1\n%d\n",a[2],n);}else {printf("%d %d\n2\n%d %d\n",a[1],a[2],a[1]-1,a[2]+1);}return 0;}if(cnt>2) {printf("Impossible"); return 0;}if(cnt==1){for(int i=1; i<=m; i++) if(a[i]&1) {swap(a[i],a[1]); break;}}else{int flag = 0;for(int i=1; i<=m; i++) if(a[i]&1) {flag++; if(flag==1) swap(a[i],a[1]); else {swap(a[i],a[m]); break;}}}for(int i=1; i<=m; i++) printf("%d ",a[i]); puts("");printf("%d\n",a[1]==1 ? m-1 : m);if(a[1]>1) printf("%d ",a[1]-1);for(int i=2; i<=m; i++) printf("%d ",a[i]+(i==m?1:0)); puts("");return 0; }總結
以上是生活随笔為你收集整理的AtCoder AGC001D Arrays and Palindrome (构造)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [做题记录]AtCoder AGC做题记
- 下一篇: AtCoder AGC001E BBQ