从4*n-2开始,每次输出减2。
发现满足条件,不互质也不能相互整除
引爆花费a,安装花费b
可知要引爆必定花费一个a,ans+=a
对于两段1区间中间隔着的0,既可以用安装一个个1花费 cnt*b 也可以花费a引爆
那么每次记录下来,然后比较 ans+=min(cnt*b,a)就行
代码不贴了,开始想复杂了,导致过的很慢,码风也很丑陋
给定两个序列,表示 取走某一个物品的a值和b值。
我们要取每一个物品,通过a值取的贡献取大,通过b值取的贡献累加,最后两者再取大。
思路就很明显了,按a排序,每次取i,那么i之前的物品都可以通过a值取,也就是没有花费。
i之后的物品,累加b值,然后两者取大,就是该做法的最后答案。
ll ans,sum[200007]; struct nod{ ll a,b; }node[200007]; int cmp(nod x,nod y){ return x.a<y.a; } int t,n; int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); ans=inf; for(int i=1;i<=n;++i) scanf("%lld",&node[i].a); for(int i=1;i<=n;++i) scanf("%lld",&node[i].b); sort(node+1,node+1+n,cmp); for(int i=1;i<=n;++i) sum[i]=sum[i-1]+node[i].b; for(int i=1;i<=n;++i){ if(node[i].a>sum[n]-sum[i]) ans=min(ans,node[i].a); else ans=min(ans,sum[n]-sum[i]); } ans=min(ans,node[n].a); ans=min(ans,sum[n]); printf("%lld\n",ans); } return 0; }
思路二:二分
不对a进行排序,直接对答案进行二分,判断当前的答案是否能满足条件。
如果物品i的a值大于我的答案x,那么sum累加b值。
如果最后b值反而大于x,那么不成立。
成立的话说明,x还能继续缩小,让更多的物品去贡献b值到sum。
以下是队友优秀的码风
ll a[N],b[N],n; int check(ll x){ ll ans=0; FR(i,1,n) if(a[i]>x)ans+=b[i]; if(ans>x)return 0; return 1; } int main(){ int t; string s; scanf("%d",&t); while(t--){ scanf("%lld",&n); ll sum=0,maxn=0; FR(i,1,n){ scanf("%lld",&a[i]); maxn=max(maxn,a[i]); } FR(i,1,n){ scanf("%lld",&b[i]); sum+=b[i]; } ll l=1,r=max(maxn,sum); ll mid; while(l!=r){ mid=(l+r)/2; if(check(mid))r=mid; else l=mid+1; } printf("%lld\n",l); } return 0; }
两种操作法,一种是从头到i都减1,第二种事从尾到1
Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)
原文:https://www.cnblogs.com/PdrEam/p/13923254.html