R311 DIV2 C. Arthur and Table
飞机票:http://codeforces.com/contest/557/problem/C
题意:给你个桌子,有n个桌脚(n<=1e5),每个桌脚有个高度为ai,拆掉每个桌脚需要力量bi,现在问你拆除桌脚使桌子稳定,且用力最小,桌子稳定的条件是最大的那个脚的总数必须大于当前脚数量的一半,假设有当前有5个桌脚,要使稳定,需要3个最大的脚,假设4个,则要3个最大脚,只有1个他就是稳定的。
分析:我们可以枚举脚的长度,怎么枚举??按脚长度排个序,然后假设长度为k的脚的数量从l到r,即有r-l+1个为k的数量。然后我们可以来个辅助数组ci,就是大于k脚长度需要花费的总力气,这个力气可以从后往前推,因为我们是从小到大对脚长度进行排序,那么初始必须花费的力气是c[r+1],然后我们有r-l+1的数量,设为sum,则我们可以保留sum-1(因为大于一半)个脚,因为前面有l-1个脚,我们可以拆除l-1-(sum-1)个脚。设为des,如果des<=0,则不用拆了,因为我们已经足够,如果大于0,则要从前面l-1选择des个脚拆除,我们贪心的话,肯定会拆需要力量最小的脚,因为力量<=200,所以我们可以用个数组need[200]表示前面各个力量有多少个然后从小到达选择des个,设为力量需要为p,这总共需要力量c[r+1]+p,然后去最小值因为我们要处理need[200],所以我们要一个辅助数组记录l到r需要的各个力量,然后处理完l~r则把辅助数组的数据加到need上去,让下一次可以继续迭代,复杂度O(n*200),最后啪啪啪就可以AC了
/* Author:Chieh Because Of Coding */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <map> #include <stack> #include <queue> #include <vector> #define LL long long #define INF 1e9 #define EPS 1e-9 using namespace std; const int maxn=123456; int n; struct he { int len,val; } Sky[maxn]; bool cmp(he a, he b) { return a.len<b.len; } int bi[maxn]; int ai[234]; int ci[234]; void init() { for(int i=1; i<=n; i++) { scanf("%d",&Sky[i].len); } for(int i=1; i<=n; i++) { scanf("%d",&Sky[i].val); } sort(Sky+1,Sky+1+n,cmp); bi[n+1]=0; for(int i=n; i>=1; i--) { bi[i]=Sky[i].val; bi[i]+=bi[i+1]; } Sky[n+1].len=INF; Sky[0].len=0; } void play() { memset(ai,0,sizeof(ai)); int l=-1; int MIN=INF; memset(ci,0,sizeof(ci)); for(int i=1; i<=n+1; i++) { if(Sky[i].len!=Sky[i-1].len) { if(l!=-1) { int ok=(i-1-l)+1; int xy=ok-1; xy=l-1-xy; int sum=bi[i]; if(xy>0) { for(int j=1; j<=200; j++) { if(xy<=ai[j]) { sum+=xy*j; break; } else { xy-=ai[j]; sum+=ai[j]*j; } } } if(sum<MIN)MIN=sum; } for(int j=1; j<=200; j++) { ai[j]+=ci[j]; } l=i; memset(ci,0,sizeof(ci)); int v=Sky[i].val; ci[v]++; } else { int v=Sky[i].val; ci[v]++; } } printf("%d\n",MIN); } int main() { while(scanf("%d",&n)!=EOF) { init(); play(); } // cout << "Hello world!" << endl; return 0; }