CF 1110 D/E
阿新 • • 發佈:2019-02-08
getchar namespace har def nes ios eof tchar inline 表示\(DP\)到編號為\(i\)的瓷磚,以\(i-1\)結尾的連續匹配進行了\(j\)次,以\(i\)結尾的連續匹配進行了\(k\)次的最大三元組數。
數組求出來,排序後直接比較就行了。還有要判斷\(c_1==t_1\)。
CF 1110 D. Jongmah
題目大意:給你?\(n\)個瓷磚,每塊瓷磚上有一個數字?\(a_i,(1\leq a_i\leq m)\)。你可以將三個有連續數字?\((比如3,4,5)\)的瓷磚或者三個數字相同?\((比如7,7,7)\)的瓷磚組成一個三元組。每個瓷磚只能用一次。問最多可以得到多少個三元組。?
比賽的時候好像全場A穿,然而並沒有想到 (TAT。
一開始想到\(DP\),但是?覺得狀態數太大;於是想了奇奇怪怪的貪心,但是都能找到反例。
這道題的關鍵是要發現一個性質:同一位置上連續三個瓷磚匹配不會超過\(2\)個。因為如果湊夠了\(3\)個就可以分別單獨匹配了。這樣一來狀態數就少了:設\(f[i][j][k]\)
代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<set> #include<queue> #include<vector> #include<map> #define ll long long #define N 1000005 using namespace std; inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m; int f[N][3][3],sum[N]; int main() { n=Get(),m=Get(); int a; for(int i=1;i<=n;i++) { a=Get(); sum[a]++; } memset(f,-0x3f,sizeof(f)); f[2][0][0]=0; for(int i=2;i<m;i++) { for(int j=0;j<3;j++) { for(int k=0;k<3;k++) { if(f[i][j][k]<0) continue ; for(int q=0;q<3;q++) { if(sum[i+1]<q) break; if(sum[i]<k+q) break; if(sum[i-1]<j+k+q) break; f[i+1][k][q]=max(f[i+1][k][q],f[i][j][k]+(sum[i-1]-j-k-q)/3+q); } } } } int ans=0; for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans=max(ans,f[m][i][j]+(sum[m]-j)/3+(sum[m-1]-i-j)/3); cout<<ans; return 0; }
總結:發現這種非一般套路的\(DP\)或者貪心題時要去發現題目的特殊性質,往往特殊性質是解題的關鍵。
CF 1110 E. Magic Stones
題目大意:給你兩個長度為\(n\)的序列\(c\)和\(t\)。你可以對\(c\)進行任意次操作,每次操作選取位置\(i(2\leq i\leq n-1)\),然後將\(c_i\)變成\(c_{i-1}+c_{i+1}-c_i\)。
這題太神了,不過好像比賽時也被A穿了。
我們設\(d_i=c_{i+1}-c_i(1\leq i \leq n-1)\)。我們會發現,對\(c_i\)進行上述操作後,交換了\(d_{i-1}\)與\(d_i\)。
所以我們將兩個數列的\(d\)
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define N 200005
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
int n;
int c[N],t[N];
int dc[N],dt[N];
int main() {
n=Get();
for(int i=1;i<=n;i++) c[i]=Get();
for(int i=1;i<=n;i++) t[i]=Get();
for(int i=1;i<n;i++) dc[i]=c[i+1]-c[i];
for(int i=1;i<n;i++) dt[i]=t[i+1]-t[i];
if(c[1]!=t[1]) {cout<<"No";return 0;}
sort(dc+1,dc+n);
sort(dt+1,dt+n);
for(int i=0;i<=n;i++) {
if(dc[i]!=dt[i]) {cout<<"No";return 0;}
}
cout<<"Yes";
return 0;
}
CF 1110 D/E