Submission #469974

#TimeUsernameProblemLanguageResultExecution timeMemory
469974NamnamseoHarvest (JOI20_harvest)C++17
100 / 100
1136 ms176712 KiB
#include <algorithm>
#include <iostream>
#include <numeric>
#include <tuple>
#include <vector>
#define rep(i, n) for (int i=0; i<n; ++i)
#define rrep(i, n) for (int i=1; i<=n; ++i)
#define all(v) v.begin(), v.end()
#define pb push_back
using namespace std;
using ll=long long; using pp=pair<int,int>;
using vi=vector<int>; using vll=vector<ll>;
const int maxn = int(2e5) + 10;

int n;

struct MergeSortTree {
	const static int M = 262144;
	vll t[M<<1];
	void add_point(int x, ll y) { for (x+=M; x; x/=2) t[x].pb(y); }
	void init() {
		for (int i=1; i<M; ++i) sort(all(t[M+i]));
		for (int i=M-1; 1<=i; --i) {
			auto &v = t[i], &vl = t[i*2], &vr = t[i*2+1];
			if (vl.empty()) v = vr; else if (vr.empty()) v = vl;
			else v.resize(vl.size()+vr.size()), merge(all(vl), all(vr), v.begin());
		}
	}
	int rect(int l, int r, ll u) {
		int ret = 0;
		auto qv = [&](vll &v) { ret += (upper_bound(all(v), u)-v.begin()); };
		for (l+=M, r+=M; l<=r; l/=2, r/=2) {
			if (l%2==1) qv(t[l++]);
			if (r%2==0) qv(t[r--]);
		}
		return ret;
	}
	int rect(int l, int r, ll d, ll u) {
		int ret = 0;
		auto qv = [&](vll &v) { ret += (upper_bound(all(v), u)-lower_bound(all(v), d)); };
		for (l+=M, r+=M; l<=r; l/=2, r/=2) {
			if (l%2==1) qv(t[l++]);
			if (r%2==0) qv(t[r--]);
		}
		return ret;
	}
};

int nxt[maxn], nxtd[maxn];
vi apples[maxn];

namespace Step1 {
int m, L, C;
int person[maxn], apple[maxn];
void In() {
	cin.tie(0)->sync_with_stdio(0);
	cin >> n >> m >> L >> C;
	rrep(i, n) cin >> person[i];
	rrep(i, m) cin >> apple[i];
}

pp GetNxt(int pos) {
	int i = int(upper_bound(person+1, person+n+1, pos)-person)-1;
	if (i == 0) return {n, (L-person[n])+pos};
	else return {i, pos-person[i]};
}

void BuildNxt() {
	rrep(i, n) {
		int t = person[i]-C%L; if (t < 0) t += L;
		tie(nxt[i], nxtd[i]) = GetNxt(t);
		nxtd[i] += C;
	}
}

void AddApples() {
	rrep(i, m) {
		int j, d; tie(j, d) = GetNxt(apple[i]);
		apples[j].emplace_back(d);
	}
}

void Work() {
	In();
	BuildNxt(); AddApples();
}
}

int cn;
int myci[maxn];
int croots[maxn];
ll crdst[maxn];
ll clen[maxn];
vector<int> celem[maxn];
bool iscv[maxn];
int tin[maxn], tout[maxn];

namespace Step2 {
bool onstk[maxn];
void dfs1(int x) {
	onstk[x] = true;
	int y = nxt[x];
	if (!onstk[y]) {
		if (!myci[y]) dfs1(y);
		myci[x] = myci[y];
		crdst[x] = crdst[y] + nxtd[x];
		onstk[x] = false;
		return;
	}
	myci[x] = ++cn; croots[cn] = x; iscv[x] = true;
	celem[cn].pb(x);
	for (int y=nxt[x]; y!=x; y=nxt[y]) celem[cn].pb(y);
	onstk[x] = false;
}

vector<int> child[maxn];
int nt;
void dfs2(int x) {
	tin[x] = ++nt;
	for (int y:child[x]) {
		dfs2(y);
	}
	tout[x] = nt;
}

void BuildGraph() {
	rrep(i, n) if (!myci[i]) dfs1(i);
	rrep(i, n) if (celem[myci[i]][0] != i) child[nxt[i]].pb(i);
	rrep(i, cn) { int r = croots[i];
		for (int x:celem[i]) {
			iscv[x] = true;
			clen[i] += nxtd[x];
		}
		dfs2(r);
	}
}
}

MergeSortTree tconst, tinf;
vector<ll> rdl[maxn], rdp[maxn];
int xoff[maxn], xoz;
ll cp[maxn];

namespace Step3 {
void Build() {
	rrep(i, n) for (int ad:apples[i]) tconst.add_point(tin[i], crdst[i]+ad);
	tconst.init();

	rrep(v, n) for (int ad:apples[v]) rdl[myci[v]].pb(crdst[v]+ad);
	rrep(ci, cn) {
		sort(all(rdl[ci])), rdp[ci].resize(rdl[ci].size());
		xoff[ci] = xoz;
		xoz += rdl[ci].size();
	}

	rrep(v, n) for (int ad:apples[v]) {
		int ci = myci[v];
		auto &vl=rdl[ci], &vp=rdp[ci];
		ll tt = crdst[v] + ad, cl = clen[ci];
		int x = int(lower_bound(all(vl), tt)-vl.begin())+1;

		ll tn = tt/cl, tr = tt%cl;
		tn = -tn-1; tr = cl-tr;
		if (tr == cl) ++tn, tr = 0;

		tinf.add_point(xoff[ci]+x, tr);
		vp[x-1] += tn;
	}

	rrep(ci, cn) partial_sum(all(rdp[ci]), rdp[ci].begin());
	tinf.init();

	rrep(ci, cn) {
		ll pt = 0;
		for (int x:celem[ci]) cp[x]=pt, pt+=nxtd[x];
		cp[celem[ci][0]] = pt;
	}
}
}

int CountConst(int v, ll T) {
	return tconst.rect(tin[v], tout[v], crdst[v]+T);
}

ll CountInf(int v, ll T) {
	int ci = myci[v];
	ll p = cp[v], cl = clen[ci];
	ll np = (T-p)/cl, rp = (T-p)%cl;
	if (rp < 0) rp+=cl, --np;

	auto &vl = rdl[ci], &vp = rdp[ci];
	int xr = upper_bound(all(vl), T-p)-vl.begin();
	if (!xr) return 0;

	ll ret = xr * (1 + np) + (xr ? vp[xr-1] : 0);
	ret += tinf.rect(xoff[ci]+1, xoff[ci]+xr,
		cl-rp, cl);

	return ret;
}

int main() {
	Step1::Work();
	Step2::BuildGraph();
	Step3::Build();

	int q; cin >> q;
for (;q--;) {
	int v; ll T; cin >> v >> T;

	ll ans = CountConst(v, T);
	if (iscv[v]) ans += CountInf(v, T);

	cout << ans;
	cout << '\n';
}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...