Codeforces Round #683 (Div. 2, by Meet IT)
阿新 • • 發佈:2020-11-16
A - Add Candies
題面:題面有點繞,總結一下就是有n個長度的陣列,陣列值跟下標值一樣,a[i]=i;然後問你第i次操作,選一個數組中的值,除了它其他都加i,使得陣列值相同,問隨機一種情況
思路:操作n次,輸出1,2,3,4,5 … n即可
B - Numbers Box
題面:給一個n,m的矩陣,有正負,有操作選兩個相鄰的值,同乘-1,求這個矩陣最大的之和
思路:比賽的時候卡了,因為沒想清楚,選了個最小的負數,其實,正解是如果出現奇數個負數,選擇最小的abs值,偶數個負數就肯定能全部變正
比賽的時候隊友飛快過三題,然後我還在卡B,如果不是隊友提醒,可能卡死了
C - Knapsack
題面:給兩個數n,w,給n長度陣列,求數組裡選幾個有沒有w/2~w範圍的值
思路:第一想法揹包,但資料n 2e5,w 1e18,好,肯定不行,換一個,排序然後尺取?,於是寫了一下,就過了
#include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long #define lson(x) x<<1 #define rson(x) x<<1|1 #define mod 998244353 using namespace std; ll ksm(ll a,ll b){ ll ans=1; while(b){ if(b&1){ ans*=a;ans%=mod; } a*=a;a%mod; b>>=1; } } const int N=2e5+10; int n,m,t; ll w; ll dp[N]; struct node{ int w,num; friend bool operator<(const node a,const node b){ return a.w<b.w; } }we[N]; int main(){ scanf("%d",&t); while(t--){ scanf("%d%lld",&n,&w); int f=1,pos; for(int i=0;i<n;i++){ scanf("%lld",&we[i].w);we[i].num=i+1; if(we[i].w*2>=w && we[i].w<=w){ f=0;pos=i; } } if(!f){ printf("1\n"); printf("%d\n",we[pos].num); continue; } sort(we,we+n); dp[0]=we[0].w; for(int i=1;i<n;i++){ dp[i]=dp[i-1]+we[i].w; } for(int i=0;i<n;i++){ if(dp[i]*2>=w && dp[i]<=w){ f=0;pos=i;break; } if(dp[i]*2>=w && dp[i]>w){ f=2;pos=i;break; } } int pos2=0; if(f==2){ for(int i=0;i<pos;i++){ while((dp[pos]-dp[i])*2<w){pos++;if(pos>n){break;}} if((dp[pos]-dp[i])*2>=w &&(dp[pos]-dp[i])<=w){f=0,pos2=i;break;} } } if(!f){ printf("%d\n",pos-pos2+1); for(int i=pos2;i<=pos;i++){ printf(i==pos?"%d\n":"%d ",we[i].num); } } else{ printf("-1\n"); } } return 0; }
D - Catching Cheaters
題面:給n,m兩個小於5000的數字,然後輸入兩個長度為n,m 的字串s1,s2,取兩個子串s1’,s2’長度分別是x,y,求4 * lcs(s1’,s2’)-x-y的最大值
思路:列舉二分貪心wa,因為沒考慮n長度字串的選子串的字母,是個假演算法。所以這道題正解就是dp,每次dp題,貪心貪出事。
那麼方法就是,每次找到相同的字元,就會對前一個狀態+2,如果沒有相同,就會有兩種選擇,移動s1一位,or移動s2一位,每移動一位值就會-1
這樣我們就可以列出狀態轉移方程
**s1[i]==s2[j] 的情況 **比較 dp[i-1][j-1]+2 dp[i-1][j]-1(大於等於0) dp[i][j-1]-1(大於等於0) 哪個大
**s1[i]!=s2[j] 的情況 **比較 dp[i-1][j]-1(大於等於0) dp[i][j-1]-1(大於等於0) 哪個大
然後找dp[i][j]的最大值即可
程式碼:
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define lson(x) x<<1
#define rson(x) x<<1|1
#define mod 998244353
using namespace std;
ll ksm(ll a,ll b){
ll ans=1;
while(b){
if(b&1){
ans*=a;ans%=mod;
}
a*=a;a%mod;
b>>=1;
}
}
const int N=5e3+10;
int n,m,t;
char s[N],ss[N];
int dp[N][N];
int main(){
scanf("%d%d",&n,&m);
scanf("%s",s);
scanf("%s",ss);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i]==ss[j]){
dp[i+1][j+1]=max(dp[i][j]+2,max(max(dp[i+1][j]-1,0),max(dp[i][j+1]-1,0)));
}
else{
dp[i+1][j+1]=max(max(dp[i+1][j]-1,0),max(dp[i][j+1]-1,0));
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ans=max(dp[i][j],ans);//cout<<dp[i][j]<<" ";
}
//cout<<endl;
}
printf("%d\n",ans);
return 0;
}