7.11洛谷多校5補
阿新 • • 發佈:2021-07-11
A
長度為n的包含小寫字母的字串,有m種變換關係,可以把某個字母花費一定代價變成另一個字母,某個字串被變為迴文串的代價稱為最小回文代價,對所有子串,求最小回文代價的和。
n<=10^5
題解:
一開始我看錯題了,以為這個代價是隻要首尾相同就行了,打完之後發現錯了。
但實際上沒什麼區別,改了一點點又過了。
首先用floyd求兩兩字母變成相同的所需的最小代價f[x][y]
考慮兩個位置i<j,這兩個位置產生的代價是min(i,n-j+1)*f[s[x]][s[y]]
這個代價可以用字首和來算。
程式碼:
1 #include<bits/stdc++.h> 2 using namespacestd; 3 int a[100010],f[30][30],aa[30][30],c[30],ss[100010][30]; 4 long long st[100010][30]; 5 int main() 6 { 7 int n,m; 8 scanf("%d%d",&n,&m); 9 char s[1000010]; 10 scanf("%s",s+1); 11 for (int i=1;i<=n;i++) a[i]=s[i]-'a',c[a[i]]++; 12 getchar(); 13 for (int i=0;i<=25;i++) for(int j=0;j<=25;j++) f[i][j]=f[j][i]=30*20000; 14 for (int i=0;i<=25;i++) f[i][i]=0; 15 for (int i=1;i<=m;i++) 16 { 17 char x,y; 18 int z; 19 scanf("%c %c %d",&x,&y,&z); 20 getchar(); 21 f[x-'a'][y-'a']=z; 22 } 23 for (int k=0;k<=25;k++) for (int i=0;i<=25;i++) for (int j=0;j<=25;j++) if (i!=j&&i!=k&&j!=k) f[i][j]=min(f[i][j],f[i][k]+f[k][j]); 24 for (int i=0;i<=25;i++) for (int j=0;j<=25;j++) 25 { 26 if (i==j) continue; 27 aa[i][j]=min(f[i][j],f[j][i]); 28 for (int k=0;k<=25;k++) if (i!=k&&j!=k) aa[i][j]=min(aa[i][j],f[i][k]+f[j][k]); 29 } 30 long long ans=0; 31 for (int i=1;i<=n;i++) for (int j=0;j<=25;j++) 32 { 33 ss[i][j]=ss[i-1][j]; 34 st[i][j]=st[i-1][j]; 35 if (j==a[i]) ss[i][j]++,st[i][j]+=i; 36 } 37 for (int i=1;i<=n;i++) 38 { 39 for (int j=0;j<=25;j++) 40 { 41 if (a[i]==j) continue; 42 int mn=30*20000; 43 mn=min(aa[j][a[i]],min(aa[a[i]][j],mn)); 44 if (mn==30*20000) continue; 45 int tt=n-i; 46 if (i>=tt+2) ans=ans+1ll*st[tt+1][j]*mn+1ll*(ss[i-1][j]-ss[tt+1][j])*(tt+1)*mn; 47 else ans=ans+1ll*st[i][j]*mn; 48 } 49 } 50 printf("%lld\n",ans); 51 }
B
兩個01串,一個操作序列,這個操作序列表示,第i天會把第a[i]位取反,每天有一次額外的機會修改串的某一位,問最早哪一天可以使得兩個串相同。
<=10^5
題解:
二分答案,直接模擬判斷即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[200020],b[200020],c[200020]; 4 int main() 5 { 6 int n,t; 7 scanf("%d%d",&n,&t); 8 char s1[200010],s2[200010]; 9 scanf("%s",s1+1); 10 scanf("%s",s2+1); 11 for (int i=1;i<=t;i++) scanf("%d",&a[i]); 12 int l=0,r=t,ans=-1; 13 while (l<=r) 14 { 15 int mid=l+r>>1; 16 for (int i=1;i<=n;i++) b[i]=s1[i]-'0',c[i]=s2[i]-'0'; 17 for (int i=1;i<=mid;i++) b[n-a[i]]=1-b[n-a[i]]; 18 int tmp=0; 19 for (int i=1;i<=n;i++) if (b[i]!=c[i]) tmp++; 20 if (tmp<=mid) 21 { 22 ans=mid; 23 r=mid-1; 24 }else l=mid+1; 25 } 26 if (ans!=-1) printf("%d\n",ans);else printf("icu\n"); 27 }
E
ABC三種磚塊,A只有一塊,BC無使用限制。
給定一個目標圖形,磚塊之間不能重疊,問在使用了A的情況下不同的方案數及方案。
兩個方案不同,當且僅當A放置的位置不同
n,m<=500
題解:
喵喵喵,太喵了
觀察可以發現,A所在的對角線,一定有奇數個格子需要被覆蓋。
這樣就可以把A所在區域縮小到O(n+m)級別。
剩下就是暴力判斷了
不得不說,喵得離譜