天天看点

暴力枚举 C. Arthur and Table

链接:http://codeforces.com/problemset/problem/557/C

直接暴力枚举即可

注意d的范围为1-200

这样维护就比较简单了

代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
#define For(i,n) for(int i=0;i<n;i++)
#define MAX 100005
int ans[201];
int b[MAX];
int f[MAX];
struct node{
	int l;
	int v;
	int cnt;
}mp[MAX];
bool cmp(node x,node y){
	return x.l < y.l;
}
int main(void){
	int sum = 1e8;
	int n;cin >> n;
	For(i,n) cin >> mp[i].l; 
	For(i,n) cin >> mp[i].v;
	sort(mp,mp+n,cmp);
	for(int i =0;i<n;i++){
		int cnt=1,t = i;
		while(mp[i].l == mp[i+1].l)cnt++,i++;
		mp[t].cnt = cnt;	
	}
	f[0]=mp[0].v;
	For(i,n)if(i>=1)f[i]=f[i-1]+mp[i].v;
	for(int i = n-1;i>=0;i--)b[i]=b[i+1]+mp[i].v;
	for(int i = 0;i < n;){
		int cnt = mp[i].cnt -1 ;
		int s = b[i+mp[i].cnt];
		int t = 0;
		for(int j=200; j>=1;j--){
			if(ans[j] && cnt){
				if(ans[j]>=cnt){t+=j*cnt;break;}
				else t+= j*ans[j], cnt -= ans[j];
			}
		}
		s += f[i-1]-t;
		sum = min(sum,s);
		for(int j = i;j < i + mp[i].cnt;j++)ans[mp[j].v]++;
		i+=mp[i].cnt;
	}
	cout << sum <<endl;
}