Codeforces Global Round 1 (D、E)
D.Jongmah
题目大意
给定若干块有类型的砖块,要求类型序号连续的三元组和序号相同的三元组可以组成一个,问给定的类型序列最多可以组成多少块。(砖块数和类型数均 ≤ 1 e 6 \leq1e6 ≤1e6)
解题思路
定义 d p dp dp状态为 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]在 i i i位置,有 j j j个形如 i − 1 , i , i + 1 i-1,i,i+1 i−1,i,i+1的三元组,有 k k k个形如 i , i + 1 , i + 2 i,i+1,i+2 i,i+1,i+2的三元组,则易得出状态转移方程为 d p [ i + 1 ] [ k ] [ j ] = m a x ( d p [ i + 1 ] [ k ] [ j ] , d p [ i ] [ j ] [ k ] + ( a [ i + 1 ] − j − k − p ) / 3 + p ) dp[i+1][k][j]=max(dp[i+1][k][j],dp[i][j][k]+(a[i+1]-j-k-p)/3+p) dp[i+1][k][j]=max(dp[i+1][k][j],dp[i][j][k]+(a[i+1]−j−k−p)/3+p),故最后答案为 d p [ m + 1 ] [ 0 ] [ 0 ] dp[m+1][0][0] dp[m+1][0][0]
std
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[1000005];
int dp[1000005][3][3];
int main(){
memset(dp,-1,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
a[x]++;
}
dp[0][0][0]=0;
for(int i=0;i<=m;i++){
for(int j=0;j<3;j++){
for(int k=0;k<3;k++){
int num=a[i+1]-j-k;
if(dp[i][j][k]==-1)continue;
for(int l=0;l<=min(2,num);l++){
dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+(num-l)/3+l);
}
}
}
}
printf("%d\n",dp[m+1][0][0]);
return 0;
}
E. Magic Stones
题目大意
给你两个数组c、t,你可以进行若干次操作,对于每次操作,你可以选择一个索引为 i ( 2 ≤ i ≤ n − 1 ) i(2\leq i\leq n-1) i(2≤i≤n−1),使得 c i c_i ci变为 c i − 1 + c i + 1 − c i c_{i-1}+c_{i+1}-c_{i} ci−1+ci+1−ci,问能否将数组c转化成数组t,能输出 Y e s Yes Yes,否则输出 N o No No
解题思路
当我们把 c i c_i ci变成 c i − 1 + c i + 1 − c i c_{i-1}+c_{i+1}-c_{i} ci−1+ci+1−ci后, c i + 1 − c i c_{i+1}-c_{i} ci+1−ci变成为 c i − c i − 1 , c i − c i − 1 c_{i}-c_{i-1},c_{i}-c_{i-1} ci−ci−1,ci−ci−1变成为 c i + 1 − c i c_{i+1}-c_{i} ci+1−ci,不难发现一次操作后两个差交换了,所以操作的本质就是交换相邻差的过程。那么就好判断了,把两个序列差分一下存起来比较下即可。
std
#include<bits/stdc++.h>
using namespace std;
int n;
int c[100005];
int t[100005];
int main() {
scanf("%d",&n);
vector<int>a,b;
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
for(int i=1;i<=n;i++)
scanf("%d",&t[i]);
for(int i=2;i<=n;i++){
a.emplace_back(c[i]-c[i-1]);
b.emplace_back(t[i]-t[i-1]);
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
if(a==b&&c[0]==t[0]&&c[n]==t[n])printf("Yes\n");
else printf("No\n");
return 0;
}