题意:桌子有若干个腿,只有长度最长的腿的数目是所有腿的数目的一半以上的时候才是稳定的,去掉每个腿有一个花费,现在问最小花费是多少
思路:注意这个题有个关键点就是d的值非常小,只有200,实际上这个问题可以总结为下面这个问题:前x个数中最小的k个数的和是多少?只要解决这个问题,本题也就迎刃而解了,而这个子问题由于d很小,可以记录d值出线的次数,然后O(d)暴力就好,当然也可以二分,更快。
然后这一场终于第一次紫名了!!!感觉努力了一年还是有点成果的。。虽然只是刚刚上1700,但是这对我来说意义重大!!
#include<bits/stdc++.h> #define pb push_back using namespace std; typedef long long ll; const int maxv=2e5+50; int n; struct S{ int l,d; }T[maxv]; bool cmp(S a,S b){ return a.l<b.l; } vector<S> V; int contd[303]; int getless(int x){ if(x<=0) return 0; int add=0,cont=0; for(int i=1;i<205;i++){ if(cont+contd[i]>=x){ return add+i*(x-cont); }else{ cont+=contd[i]; add+=i*contd[i]; } } } int sumsq[maxv]; int main(){ ///freopen("/home/files/CppFiles/in","r",stdin); cin>>n; int tol=0; for(int i=0;i<n;i++) scanf("%d",&T[i].l); for(int i=0;i<n;i++){ scanf("%d",&T[i].d); tol+=T[i].d; } sort(T,T+n,cmp); sumsq[0]=T[0].d; for(int i=1;i<n;i++){ sumsq[i]=sumsq[i-1]+T[i].d; } int lastmax=-1; int maxnum=0; int ans=1e9; int sum=0; int maxsum=0; for(int i=0;i<n;i++){ if(T[i].l!=lastmax){ lastmax=T[i].l; maxnum=1; maxsum=T[i].d; int k=i+1; while(k<n&&T[k].l==T[i].l){ maxnum++; maxsum+=T[k].d; k++; } ans=min(ans,tol-sumsq[k-1]+getless(k-maxnum-(maxnum-1))); contd[T[i].d]++; }else{ contd[T[i].d]++; } } cout<<ans<<endl; return 0; }