20190803
A.
解
注意,每種顏色僅出現一次。
因此樹狀數組維護所有操作的左右端點, \(答案=目前已完成的操作數-[1,當前操作左端點-1]中的右端點個數-[當前操作右端點+1,n]中的左端點個數\) 。
Code
#include<bits/stdc++.h> using namespace std; const int maxn=100003; int n,Q,tot; struct BIT{int t[maxn];BIT(){memset(t,0,sizeof(t));}void add(int pos,int k){while(pos<=n)t[pos]+=k,pos+=pos&-pos;}int query(int pos){int ret=0;while(pos)ret+=t[pos],pos-=pos&-pos;return ret;}int query(int l,int r){return l<=r?query(r)-query(l-1):0;} }treel,treer; int main(){scanf("%d%d",&n,&Q);while(Q--){int mo,l,r;scanf("%d%d%d",&mo,&l,&r);if(mo==1){treel.add(l,1);treer.add(r,1);tot++;}else{printf("%d\n",tot-treer.query(1,l-1)-treel.query(r+1,n));}}return 0; }B.
解
直接背包,每次轉移維護前 \(k\) 大的值。
Code
#include<bits/stdc++.h> using namespace std; const int maxk=53,maxv=5003,maxn=203; int k,v,n,V[maxn],A[maxn]; struct T{int a[maxk];T(){memset(a,0,sizeof(a));}T merge(const T &t,int val){T ret;int i=1,j=1;for(;i<=*a&&j<=*t.a&&*ret.a<k;){if(a[i]>t.a[j]+val){ret.a[++*ret.a]=a[i];i++;}else{ret.a[++*ret.a]=t.a[j]+val;j++;}}while(i<=*a&&*ret.a<k){ret.a[++*ret.a]=a[i];i++;}while(j<=*t.a&&*ret.a<k){ret.a[++*ret.a]=t.a[j]+val;j++;}return ret;} }dp[maxv]; int main(){scanf("%d%d%d",&k,&v,&n);for(int i=1;i<=n;i++)scanf("%d%d",V+i,A+i);dp[0].a[++*dp[0].a]=0;for(int i=1;i<=n;i++){for(int j=v;j>=V[i];j--){dp[j]=dp[j].merge(dp[j-V[i]],A[i]);}}int ans=0;for(int i=1;i<=k;i++)ans+=dp[v].a[i];printf("%d\n",ans);return 0; }C.
解
如果你只設一個dp數組,這道題會變得比較困難
設 \(dp1[i][j]\) 表示拿到前 \(i\) 種物品施 \(j\) 次魔法所需最小成本, \(dp2[i][j]\) 表示拿到第 \(i\) 種物品施 \(j\) 次魔法所需最小成本, \(dp[i][j]\) 表示花 \(i\) 個金幣施 \(j\) 次魔法所能獲得的最大利潤。
轉移見下。
Code
#include<bits/stdc++.h> using namespace std; const int maxn=1003,INF=1050000000; int n,m,V,K,a[maxn],b[maxn],dp1[maxn][maxn],dp2[maxn][maxn],dp[maxn][maxn]; vector<vector<int> > h[maxn]; int main(){scanf("%d%d%d%d",&n,&m,&V,&K);for(int i=1;i<=n;i++)scanf("%d%d",a+i,b+i);for(int i=1;i<=m;i++){int x,k;scanf("%d%d",&x,&k);h[x].push_back(vector<int>(k));for(int j=0;j<k;j++)scanf("%d",&h[x].back()[j]);}for(int i=1;i<=n;i++){dp2[i][0]=a[i];for(int l=1;l<=K;l++){dp2[i][l]=INF;}}for(int l=1;l<=K;l++){for(int i=1;i<=n;i++){for(auto j:h[i]){for(int p=0;p<l;p++){for(int k=1;k<=int(j.size());k++){dp1[k][p]=INF;for(int q=0;q<=p;q++){dp1[k][p]=min(dp1[k][p],dp1[k-1][p-q]+dp2[j[k-1]][q]);}}}dp2[i][l]=min(dp2[i][l],dp1[j.size()][l-1]);}}}for(int j=0;j<=K;j++){for(int k=1;k<=n;k++){for(int l=0;l<=j;l++){for(int i=dp2[k][l];i<=V;i++){dp[i][j]=max(dp[i][j],dp[i-dp2[k][l]][j-l]-dp2[k][l]+b[k]);}}}}printf("%d\n",dp[V][K]);return 0; }轉載于:https://www.cnblogs.com/BlogOfchc1234567890/p/11300926.html
總結
- 上一篇: 简单实现promise封装
- 下一篇: 霍夫变换(直线检测、圆检测)