Submission #1291670

#TimeUsernameProblemLanguageResultExecution timeMemory
1291670ortsacHorses (IOI15_horses)C++20
100 / 100
903 ms54276 KiB
#include "horses.h"
#include <bits/stdc++.h>

using namespace std;

#define int long long

const int MAXN = 5e5 + 10;
const int MOD = 1e9 + 7;

struct Big {
	int curr = 1;
	bool big = 0;
};

Big segb[4*MAXN];
int x[MAXN], y[MAXN];
int n;

Big multb(Big a, Big b) {
	Big ans;
	int x = (a.curr * b.curr);
	ans.big = (a.big || b.big);
	ans.big |= (x >= MOD);
	x %= MOD;
	ans.curr = x;
	return ans;
}

void buildb(int node, int l, int r) {
	if (l == r) {
		segb[node].curr = x[l];
		segb[node].big = 0;
		return;
	}
	int m = (l + r)/2;
	buildb(2*node, l, m);
	buildb(2*node + 1, m + 1, r);
	segb[node] = multb(segb[2*node], segb[2*node + 1]);
}

void updateb(int node, int l, int r, int po) {
	if (l == r) {
		segb[node].curr = x[l];
		segb[node].big = 0;
		return;
	}
	int m = (l + r)/2;
	if (po <= m) updateb(2*node, l, m, po);
	else updateb(2*node + 1, m + 1, r, po);
	segb[node] = multb(segb[2*node], segb[2*node + 1]);
}

Big queryb(int node, int l, int r, int tl, int tr) {
	if ((tl <= l) && (r <= tr)) return segb[node];
	if ((r < tl) || (tr < l)) return Big();
	int m = (l + r)/2;
	return multb(queryb(2*node, l, m, tl, tr), queryb(2*node + 1, m + 1, r, tl, tr));
}

struct Node {
	int val = 0, totmult = 1, po = 0;
};

Node merge(Node a, Node b) {
	Node ans;
	// ok, check which side is better
	int l = a.po + 1, r = b.po;
	Big isbig = queryb(1, 1, n, l, r);
	Big onlyy;
	onlyy.curr = y[b.po];
	onlyy.big = 0;
	isbig = multb(isbig, onlyy);
	ans.totmult = ((a.totmult * b.totmult) % MOD);
	if (isbig.big || (isbig.curr > y[a.po])) {
		ans.po = b.po;
		ans.val = ((a.totmult * b.val) % MOD);
		return ans;
	}
	ans.po = a.po;
	ans.val = a.val;
	return ans;
}

Node seg[4*MAXN];

void build(int node, int l, int r) {
	if (l == r) {
		seg[node].po = l;
		seg[node].val = ((x[l]*y[l]) % MOD);
		seg[node].totmult = x[l];
		return;
	}
	int m = (l + r)/2;
	build(2*node, l, m);
	build(2*node + 1, m + 1, r);
	seg[node] = merge(seg[2*node], seg[2*node + 1]);
}

void update(int node, int l, int r, int po) {
	if (l == r) {
		seg[node].po = l;
		seg[node].val = ((x[l]*y[l]) % MOD);
		seg[node].totmult = x[l];
		return;
	}
	int m = (l + r)/2;
	if (po <= m) update(2*node, l, m, po);
	else update(2*node + 1, m + 1, r, po);
	seg[node] = merge(seg[2*node], seg[2*node + 1]);
}

int32_t init(int32_t N, int32_t X[], int32_t Y[]) {
	n = N;
	for (int i = 1; i <= n; i++) x[i] = X[i - 1];
	for (int i = 1; i <= n; i++) y[i] = Y[i - 1];
	buildb(1, 1, n);
	build(1, 1, n);
	return seg[1].val;
}

int32_t updateX(int32_t pos, int32_t val) {
	pos++;
	x[pos] = val;
	updateb(1, 1, n, pos);
	update(1, 1, n, pos);
	return seg[1].val;
}

int32_t updateY(int32_t pos, int32_t val) {
	pos++;
	y[pos] = val;
	update(1, 1, n, pos);
	return seg[1].val;
}
#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...