Submission #423310

#TimeUsernameProblemLanguageResultExecution timeMemory
423310amoo_safar모임들 (IOI18_meetings)C++17
19 / 100
85 ms5240 KiB
#include "meetings.h"

#include <bits/stdc++.h>

#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 = 5e3 + 10;

int n, q;
vector<int> H, L, R;

ll dp[N], ans[N];


struct node {
	int l, r;
	ll val_r;
	bool type; // false add, true set
	pll lz_set; // m h
	ll lz_add;
	node (){
		l = r = 0;
		type = false;
		lz_set = pll(0, 0);
		lz_add = 0;
	}
	void Apply_Add(ll x){
		if(type){
			lz_set.S += x;
			val_r = r * lz_set.F + lz_set.S;
		} else {
			lz_add += x;
			val_r += x;
		}
	}
	void Apply_Set(pll ln){
		type = true;
		lz_set = ln;
		val_r = r * lz_set.F + lz_set.S;
	}
};
node seg[N << 2];

void Shift(int id){
	if(seg[id].type){
		seg[id << 1].Apply_Set(seg[id].lz_set);
		seg[id << 1 | 1].Apply_Set(seg[id].lz_set);
		// seg[id].lz_set = pll(0, 0);
	} else {
		seg[id << 1].Apply_Add(seg[id].lz_add);
		seg[id << 1 | 1].Apply_Add(seg[id].lz_add);
	}
	seg[id].type = false;
	seg[id].lz_add = 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 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);
	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];

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 < q; i++){
		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;
		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...