Link:
A:
贪心,对每个值都取最大值,不会有其他解使答案变优
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; typedef double db; const int MAXN=5005,INF=1<<30; struct data{int op,l,r,x;}dat[MAXN]; int n,m,mx[MAXN],vis[MAXN]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d%d",&dat[i].op,&dat[i].l,&dat[i].r,&dat[i].x); for(int i=1;i<=n;i++) { int tmp=0;mx[i]=INF; for(int j=1;j<=m;j++) if(dat[j].op==1&&i>=dat[j].l&&i<=dat[j].r) tmp+=dat[j].x; else if(dat[j].op==2&&i>=dat[j].l&&i<=dat[j].r) mx[i]=min(mx[i],dat[j].x-tmp); } for(int i=1;i<=n;i++) { if(mx[i]==INF) mx[i]=0; int tmp=mx[i]; for(int j=1;j<=m;j++) if(dat[j].op==1&&i>=dat[j].l&&i<=dat[j].r) tmp+=dat[j].x; else if(dat[j].op==2&&i>=dat[j].l&&i<=dat[j].r&&tmp==dat[j].x) vis[j]++; } for(int i=1;i<=m;i++) if(dat[i].op==2&&!vis[i]) return puts("NO"),0; puts("YES"); for(int i=1;i<=n;i++) printf("%d ",mx[i]); return 0; }
B:
答案可行性单调,二分答案
每次判断用$dp[i]$表示到$i$只要要删多少个数,$i$必取
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> P; const int MAXN=2e3+10; int n,k,l,r,dat[MAXN],dp[MAXN]; bool check(int x) { int ret=n; for(int i=1;i<=n;i++) dp[i]=i-1; for(int i=2;i<=n;i++) for(int j=1;j<i;j++) if(abs(dat[i]-dat[j])<=1ll*x*(i-j)) dp[i]=min(dp[i],dp[j]+i-j-1); for(int i=1;i<=n;i++) ret=min(ret,dp[i]+n-i); return ret<=k; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&dat[i]); l=0;r=2e9; while(l<=r) {//注意爆long long int mid=l/2+r/2+(l%2+r%2)/2; if(check(mid)) r=mid-1; else l=mid+1; } printf("%d",l); return 0; }
$i$必取这个条件一定要加,否则无法转移
同时注意二分时$l+r$可能爆$longlong$
C:
想到从前往后$dp$,每次按以$i$为左端点时对答案的贡献转移
但这样在$t[i]=s[i]$时是后项相关的,不符合$dp$要求
因此要将$t[i]=s[i]$合并在$t[i]>s[i]$中计算,$t[i]>s[i]$时的贡献变为$(pre+1)*(n-i+1)$
$dp[i][j]$:以前$i$位为左端点结果为$j$的方案数,分$t[i]>s[i]$与$t[i]<s[i]$枚举$pre$转移
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=2e3+10,MOD=1e9+7; int n,k;char s[MAXN]; ll pre[MAXN][MAXN],dp[MAXN][MAXN]; int main() { scanf("%d%d%s",&n,&k,s+1); dp[0][0]=pre[0][0]=1; for(int i=1;i<=n;i++) for(int j=0;j<=k;j++) { dp[i][j]=pre[i-1][j]*(s[i]-'a')%MOD; for(int k=0;(k+1)*(n-i+1)<=j&&k<i;k++) (dp[i][j]+=dp[i-k-1][j-(k+1)*(n-i+1)]*('z'-s[i]))%=MOD; pre[i][j]=(pre[i-1][j]+dp[i][j])%MOD; } printf("%lld",pre[n][k]); return 0; }