2018ccpc Guilin A. array merge (greed + thinking)

Give you a n array a of length N and an array b of length m, and then make the array c with the relative positions of array A and array b\sum_{i=1}^{n+m} c[i]Minimum value of

First of all, there is a small greedy idea, which is to choose the big ones first, but because there are certain restrictions in the selection, the elements in front of array a must be selected first than the elements in the back, so if you choose directly according to this idea, it is certainly not right (it is the opposite example to look for any). In fact, we can choose the large elements in the back and merge them with the elements in the front, and then choose the average number first If the average number of the latter block is larger than the former block, then the two blocks will be merged. After the merging, the A and b arrays will become monotonically decreasing, and then they will be greedy directly

#include<bits/stdc++.h>
using namespace std;
#define Sheryang main
const int maxn=2e5+7;
typedef long long ll;
const int mod=1e9+7;
///#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
///char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
#define IO cin.tie(0),ios::sync_with_stdio(false);
#define pi acos(-1)
#define PII pair<ll,ll>
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}
#define read read()
/** keep hungry and keep calm! **/
  
struct node{
	double sum;
	int cnt;
	friend bool operator <(node a,node b){
		return a.sum*b.cnt < a.cnt*b.sum;
	}
	friend node operator +(node a,node b){
		return {a.sum+b.sum,a.cnt+b.cnt};
	}
};

ll a[maxn],b[maxn];
node S[maxn],T[maxn];
vector<int> tmp;
void add(int op,int l,int r){
	
	for(int i=l;i<=r;i++){
		if(op == 1){
			tmp.push_back(a[i]);
		}else{
			tmp.push_back(b[i]);
		}
	}
	
}

int Sheryang(){
    
	int TT=read;
	for(int cas=1;cas<=TT;cas++){
		int n=read,m=read;
		
		for(int i=1;i<=n;i++){
			a[i] = read;
		}
		for(int i=1;i<=m;i++){
			b[i] = read;
		}
		
		printf("Case %d: ",cas);
		int cnt1 = 0;
		for(int i=1;i<=n;i++){
			S[++cnt1] = {a[i]*1.0,1};
			while(cnt1 > 1 && S[cnt1-1] < S[cnt1]){
				S[cnt1-1] = S[cnt1-1] + S[cnt1];
				cnt1 --;
			}
		}
		S[++cnt1] = {-1000,1};
		
		int cnt2 = 0;
		for(int i=1;i<=m;i++){
			T[++cnt2] = {b[i]*1.0,1};
			while(cnt2 > 1 && T[cnt2-1] < T[cnt2]){
				T[cnt2-1] = T[cnt2-1] + T[cnt2];
				cnt2 --;
			}
		}
		T[++cnt2] = {-1000,1};
		
		tmp.clear();
		int pos1 = 1 ,pos2 = 1 , fa = 1 , fb = 1;
		while(pos1 < cnt1 || pos2 < cnt2){
			if(S[pos1]<T[pos2]){
				add(2,fb,fb + T[pos2].cnt - 1);
				fb = fb + T[pos2].cnt ;
				pos2 ++;
			}else{
				add(1,fa,fa + S[pos1].cnt - 1);
				fa = fa + S[pos1].cnt ;
				pos1 ++;
 			}
		}
		
		ll ans = 0;
		for(int i=0;i<tmp.size();i++){
			ans += 1LL*(i+1)*tmp[i];
		}
		
		printf("%lld\n",ans);
	}
    return 0;
}

 

Tags: iOS

Posted on Sat, 09 Nov 2019 10:56:03 -0500 by carsonk