Codeforces Round #610
A题
本题只需按题目所给条件实现就可,分类讨论也很快,注意a有可能小于b
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<map> #include<algorithm> using namespace std; typedef long long ll; int main(){ int t; cin>>t; while(t--){ int a,b,c,r; cin>>a>>b>>c>>r; if(a>b) swap(a,b); if(a<=c&&c<=b){ int s1=b-a; cout<<max(0,c-a-r)+max(b-c-r,0)<<endl; } else if(c<a){ int s1=b-a; cout<<max(0,s1-max(c+r-a,0))<<endl; } else if(c>b){ int s1=b-a; cout<<max(0,s1-max(b-c+r,0))<<endl; } } }
B题
这题题意我比赛的时候没有看清,真实题意是,他不限定使用offer的次数,也就是说,当n小于k时只能一个一个买,当n大于k时我们可以选择购买k个,也可以一个个买。这也可以设计dp状态为f[i],前i个所需要的最大花费。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<map> #include<algorithm> using namespace std; typedef long long ll; const int N=2e5+10; int a[N]; int f[N]; int main(){ int t; cin>>t; while(t--){ int n,p,k; cin>>n>>p>>k; memset(f,0,sizeof f); int i; for(i=1;i<=n;i++){ scanf("%d",&a[i]); } sort(a+1,a+n+1); int res=0; for(i=1;i<=n;i++){ if(i>=k) f[i]=min(f[i-1],f[i-k])+a[i]; else f[i]=f[i-1]+a[i]; if(f[i]<=p) res=i; } cout<<res<<endl; } }
C题
本题是一道贪心问题,重点是发现假设我们加入t+1的位置不是必须要完成的时间点,那么我们就不可能在t这个位置离去,因为这样肯定不如t+1的时候离开好,所以我们需要枚举每个时间节点-1,但是要加上T这个点
特别注意的是,题目中代码是tim>=0的时候要进行更新,而不是单单>0因为如果等于0代表刚刚好在这个时刻结束,也需要更新答案
具体注释看代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<map> #include<algorithm> using namespace std; typedef long long ll; const int N=2e5+10; struct node { int t; int p; }num[N]; bool cmp(node x,node y){ return x.t<y.t; } int main(){ int m; cin>>m; while(m--){ int n,t,a,b; cin>>n>>t>>a>>b; int s1=0,s2=0; int i; for(i=1;i<=n;i++){ cin>>num[i].p; if(!num[i].p) s1++; else s2++; } for(i=1;i<=n;i++){ cin>>num[i].t; } sort(num+1,num+1+n,cmp); num[n+1].t=t+1; num[n+1].p=0; int ans=0; int st1=0; int st2=0; for(i=1;i<=n+1;i++){//枚举在ti-1处离开 if(st1>t)//现在所需要的时间已经大于总时间,不必更新 break; if(num[i-1].t!=num[i].t){//可能存在两个时间点是相等的 int tim=num[i].t-1; tim-=st1;//剩余还有多少时间可以用 int res=st2;// 之前已经累计的个数 if(tim>=0){//先做小的再做大的 res+=min(s1,tim/a); tim-=min(s1,tim/a)*a; res+=min(s2,tim/b); ans=max(ans,res); } } if(!num[i].p){ s1--; st1+=a; } else{ s2--; st1+=b; } st2++; } cout<<ans<<endl; } }
没有人不辛苦,只有人不喊疼