Submission #424449

#TimeUsernameProblemLanguageResultExecution timeMemory
424449amoo_safarMeetings (IOI18_meetings)C++11
60 / 100
5593 ms190172 KiB
#include "meetings.h"
 
#include <bits/stdc++.h>

#pragma GCC optimize("O3")

#define F first
#define S second
#define pb push_back
#define all(x) x.begin(), x.end()
 
using namespace std;
 
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const ll Inf = 1e18;
 
const int N = 75e4 + 10;
 
int n, q;
vector<int> H, L, R;
 
ll ans[N];
 
struct node {
	int r;
	ll val_r;
	bool type; // false add, true set
	pll lz_set; // m h
	// ll lz_add;
	node (){
		r = 0;
		val_r = 0;
		type = false;
		lz_set = pll(0, 0);
		// lz_add = 0;
	}
	inline void Apply_Add(ll &x){
		lz_set.S += x;
		val_r += x;
	}
	inline void Apply_Set(pll &ln){
		type = true;
		lz_set = ln;
		val_r = r * lz_set.F + lz_set.S;
	}
};
node seg[N * 3];
 
inline void Shift(int id){

	if(seg[id].type){
		// if(seg[id].lz_set != pll(0, 0)){
		seg[id << 1].Apply_Set(seg[id].lz_set);
		seg[id << 1 | 1].type = true;
		seg[id << 1 | 1].lz_set = seg[id].lz_set;
		seg[id << 1 | 1].val_r = seg[id].val_r;
		// seg[id << 1 | 1].Apply_Set(seg[id].lz_set);
		
	} else {
		if(seg[id].lz_set.S){
			seg[id << 1].Apply_Add(seg[id].lz_set.S);
			seg[id << 1 | 1].Apply_Add(seg[id].lz_set.S);
		}	
	}
	seg[id].type = false;
	seg[id].lz_set.S = 0;
}
void Add(int id, int l, int r, ll x, int L, int R){
	if(r <= L || R <= l) return ;
	if(l <= L && R <= r){
		seg[id].Apply_Add(x);
		return ;
	}
	int mid = (L + R) >> 1;
	Shift(id);
	Add(id << 1, l, r, x, L, mid);
	Add(id<<1|1, l, r, x, mid, R);
 
	seg[id].val_r = seg[id << 1 | 1].val_r;
}
void Add(int id, int l, int r, pll ln, int L, int R){
	if(r <= L || R <= l) return ;
	if(l <= L && R <= r){
		seg[id].Apply_Set(ln);
		return ;
	}
	int mid = (L + R) >> 1;
	Shift(id);
	Add(id << 1, l, r, ln, L, mid);
	Add(id<<1|1, l, r, ln, mid, R);
 
	seg[id].val_r = seg[id << 1 | 1].val_r;
}
ll Get(int id, int idx, int L, int R){
	if(L + 1 == R) return seg[id].val_r;
	int mid = (L + R) >> 1;
	Shift(id);
	if(idx < mid)
		return Get(id << 1, idx, L, mid);
	return Get(id << 1 | 1, idx, mid, R);
}
void Build(int id, int L, int R){
	seg[id].r = R - 1;
	if(L + 1 == R) return ;
	int mid = (L + R) >> 1;
	Build(id << 1, L, mid);
	Build(id<<1|1, mid, R);
}
 
int BS(int id, int l, int r, pll ln, int L, int R){
	if(r <= L || R <= l) return R;
	
	int mid = (L + R) >> 1;
	
	if(l <= L && R <= r){
		if(seg[id].val_r > seg[id].r * ln.F + ln.S)
			return R;
		if(L + 1 == R)
			return L;
		
		Shift(id);
		int res = BS(id << 1, l, r, ln, L, mid);
		if(res < mid)
			return res;
		return BS(id << 1| 1, l, r, ln, mid, R);
	}
	Shift(id);
	int res = BS(id << 1, l, r, ln, L, mid);
	if(res < mid)
		return res;
	return BS(id<<1|1, l, r, ln, mid, R);
}
 
 
int par[N], sz[N];
int Find(int u){
	if(par[u] == u) return u;
	return par[u] = Find(par[u]);
}
void Merge(int u, int v, ll md){
	u = Find(u);
	v = Find(v);
	// cerr << "^^ " << sz[u] << ' ' << sz[v] << '\n';
	assert(u < v);
	// phase 1 
 
	Add(1, v - sz[v] + 1, v + 1, 1ll * sz[u] * md, 0, n + 1);
	// cerr << "!! " << 1ll * sz[u] * md << '\n';
	// for(int i = v - sz[v] + 1; i <= v; i++){
		// cerr << "&& " << Get(1, i, 0, n + 1) << '+' << 1ll*sz[u]*md << '=';
		// Add(1, i, i + 1, 1ll * sz[u] * md, 0, n + 1);
		// cerr << Get(1, i, 0, n + 1) << '\n';
		// if(Get(1, i, 0, n + 1) == 3){
		// 	cerr << "pr : ";
		// 	for(int i = n; i >= 0; i--)
		// 		cerr << Get(1, i, 0, n + 1) << ' ';
		// 	cerr << '\n';
		// }
	// }
		// dp[i] += 1ll * sz[u] * md;
	// phase 2
	ll vl_u = Get(1, u, 0, n + 1);
 
	int lw = v - sz[v], hg = v + 1;
	int bin_s = BS(1, lw + 1, hg, pll(md, vl_u - u * md), 0, n + 1);
 
	// while(lw + 1 < hg){
	// 	mid = (lw + hg) >> 1;
	// 	ll vl = Get(1, mid, 0, n + 1);
	// 	if(vl > vl_u + md * (mid - u))
	// 		lw = mid;
	// 	else 
	// 		hg = mid;
	// }
	if(bin_s == n + 1)
		bin_s = v + 1;
	// cerr << "! " << bin_s << ' ' << hg << '\n';
	// assert(bin_s == hg);
	Add(1, v - sz[v] + 1, bin_s, pll(md, vl_u - u * md), 0, n + 1);
	// for(int i = v - sz[v] + 1; i <= v; i++){
	// 	ll vl = Get(1, i, 0, n + 1);
	// 	if(vl > vl_u + md * (i - u))
	// 		Add(1, i, i + 1, pll(0, vl_u + md * (i - u)), 0, n + 1);
	// 		// dp[i] =dp[u] + md * (i - u);
	// 	else
	// 		break;
	// }
	sz[v] += sz[u];
	par[u] = v;
}
 
vector<int> Q[N];
 
pii A[N];
pii sg[N << 2];
void BB(int id, int L, int R){
	if(L + 1 == R){
		sg[id] = A[L];
		return ;
	}
	int mid = (L + R) >> 1;
	BB(id << 1, L, mid);
	BB(id<<1|1, mid, R);
	sg[id] = max(sg[id << 1], sg[id << 1 | 1]);
}
pii GT(int id, int l, int r, int L, int R){
	if(r <= L || R <= l) return pii(-1, -1);
	if(l <= L && R <= r) return sg[id];
	int mid = (L + R) >> 1;
	return max(GT(id << 1, l, r, L, mid), GT(id << 1|1, l, r, mid, R));
}
 
 
void Solve(int rv){
	vector<int> ord(n, 0);
 
	iota(all(ord), 0);
	sort(all(ord), [&](int i, int j){
		// if(H[i] == H[j])
		return pii(H[i], rv * i) < pii(H[j], rv * j); 
	});
	
	fill(sz, sz + N, 1);
	iota(par,par +N, 0);
	// fill(dp, dp + N, 0);
	Add(1, 0, n + 1, pll(0, 0), 0, n + 1);
	for(int i = 0; i < N; i++) Q[i].clear();
	for(int i = 0; i < n; i++) A[i] = pii(H[i], rv * i);
	BB(1, 0, n);
	////////////////////////////
 
	for(int i = 0; i < q; i++){
		pii mx = GT(1, L[i], R[i] + 1, 0, n);
		int idx = mx.S / rv;
		// int idx = L[i];
		// for(int j = L[i]; j <= R[i]; j++)
		// 	if(pii(H[j], rv * j) > pii(H[idx], rv * idx))
		// 		idx = j;
		// assert(idx == idx2);
		Q[idx].pb(i);
	}
 
	for(int i : ord){
		for(int q_id : Q[i]){
			ans[q_id] = min(ans[q_id], 1ll * H[i] * (i - L[q_id] + 1) + Get(1, R[q_id] + 1, 0, n + 1));
		}
		Merge(i, i + 1, H[i]);
		// cerr << "# " << i << '\n';
		// cerr << "!! ";
		// for(int i = 0; i <= n; i++)
		// 	cerr << Get(1, i, 0, n + 1) << ' ';
		// cerr << '\n';
	}
}
 
vector<long long> minimum_costs(vector<int> _H, vector<int> _L, vector<int> _R) {
	H = _H; L = _L; R = _R;
	n = H.size();
	q = L.size();
 
	Build(1, 0, n + 1);
	fill(ans, ans + N, Inf);
 
	Solve(+1);
	
	reverse(all(H));
	for(auto &x : L) x = n - 1 - x;
	for(auto &x : R) x = n - 1 - x;
	L.swap(R);
 
	Solve(-1);
	vector<ll> ANS;
	for(int i = 0; i < q; i++)
		ANS.pb(ans[i]);
	return ANS;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...