Submission #1303349

#TimeUsernameProblemLanguageResultExecution timeMemory
1303349vlomaczkHarvest (JOI20_harvest)C++20
0 / 100
88 ms50864 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;
 
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

ll M = 200'010;
ll base = 1<<19;
ll nxt = 1,cnt;
vector<vector<ll>> adj(M), tadj(M), gscc(M);
vector<vector<pair<ll, ll>>> g(M);
vector<ll> post_order, vis(M), scc(M), ile(1), root(M), dep(M), pre(M), post(M), Tree(2*base);

void update(ll x, ll val) {
	x += base;
	Tree[x] += val;
	x/=2;
	while(x > 0) {
		Tree[x] = Tree[x+x] + Tree[x+x+1];
		x/=2;
	}
}

ll query(ll a, ll b) {
	a+=base-1;
	b+=base+1;
	ll ans = 0;
	while(a/2 != b/2) {
		if(a%2==0) ans += Tree[a+1];
		if(b%2==1) ans += Tree[b-1];
		a/=2; b/=2;
	}
	return ans;
}

void post_dfs(ll v) {
	if(vis[v]) return;
	vis[v] = 1;
	for(auto u : adj[v]) post_dfs(u);
	post_order.push_back(v);
}

void trans_dfs(ll v) {	
	scc[v] = nxt; cnt++;
	for(auto u : tadj[v]) if(!scc[u]) trans_dfs(u);
}

struct zapyt {
	ll v, t, idx;
};

vector<zapyt> queries(M);
vector<ll> ans(M);

void dfs(ll v) {
	pre[v] = ++nxt;
	for(auto[u,c] : g[v]) {
		if(scc[u]==scc[v]) continue;
		dep[u] = dep[v] + c;
		root[u] = root[v];
		dfs(u);
	}
	post[v] = nxt;
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	ll n,m,l,c;
	cin >> n >> m >> l >> c;
	vector<ll> emp(n);
	for(ll i=0; i<n; ++i) cin >> emp[i];
	vector<ll> Trees(m);
	for(ll i=0; i<m; ++i) cin >> Trees[i];
	ll q; cin >> q;
	queries.resize(q);
	for(ll i=0; i<q; ++i) {
		ll v, t;
		cin >> v >> t;
		queries[i] = {v-1,t,i};
	}
	vector<ll> poprz(m);
	vector<vector<ll>> my_tres(n);
	auto dist = [&](ll a, ll b) {
		if(a <= b) return b-a;
		return l - (a-b);
	};
	for(ll i=0; i<m; ++i) {
		ll it = lower_bound(emp.begin(), emp.end(), Trees[i]) - emp.begin();
		it--; if(it < 0) it = n-1;
		poprz[i] = it;
		my_tres[it].push_back(dist(emp[it], Trees[i]));
	}
	for(ll i=0; i<n; ++i) sort(my_tres[i].begin(), my_tres[i].end());
	ll iterator = 1%n;
	auto dist_emp = [&](ll x, ll y) {
		if(x <= y) return emp[y] - emp[x];
		else return l - (emp[x] - emp[y]);
	};
	for(ll i=0; i<n; ++i) {
		while(dist_emp((iterator+1)%n, i) >= c) iterator = (iterator+1)%n;
		adj[iterator].push_back(i);
		g[iterator].push_back({i, dist_emp(iterator, i)});
		tadj[i].push_back(iterator);
	}
	for(ll i=0; i<n; ++i) post_dfs(i);
	reverse(post_order.begin(), post_order.end());
	for(auto v : post_order) {
		if(!scc[v]) {
			cnt = 0;
			trans_dfs(v);
			ile.push_back(cnt);
			nxt++;
		}
	}	
	nxt = 1;
	for(ll i=0; i<n; ++i) {
		if(ile[scc[i]] > 1) {
			root[i] = i;
			dfs(i);
		}
	}
	vector<pair<ll, ll>> zap2;
	for(ll i=0; i<q; ++i) {
		auto[v,t,idx] = queries[i];
		if(ile[scc[v]] > 1) continue;
		zap2.push_back({t + dep[v], i});
	}
	vector<vector<ll>> subTree(n);
	for(ll i=0; i<n; ++i) {
		for(auto x : my_tres[i]) {
			zap2.push_back({dep[i] + x, -i-1});
			subTree[root[i]].push_back(dep[i] + x);
		}
	}
	sort(zap2.begin(), zap2.end());
	for(auto[czas, type] : zap2) {
		if(type<0) {
			type*=-1; type--;
			update(pre[type], 1);
		} else {
			ans[type] = query(pre[queries[type].v], post[queries[type].v]);
		}
	}
	vector<ll> vis(n);
	vector<pair<ll, ll>> next(n);
	for(ll i=0; i<n; ++i) {
		for(auto[u,c] : g[i]) {
			if(scc[u]==scc[i]) next[i] = {u,c};
		}
	}
	vector<vector<ll>> myq(n);
	for(auto[v,t,idx] : queries) myq[v].push_back(idx);
	for(ll start=0; start<n; ++start) {
		if(ile[scc[start]]==1 || vis[start]) continue;
		ll okres = 0;
		ll v = start;
		ordered_set<ll> os;
		ll dodane = 0;
		do {
			vis[v] = 1;
			for(auto x : subTree[v]) os.insert(okres + x);
			okres += next[v].second;
			v = next[v].first;
		} while(v!=start);
		if(os.empty()) continue;
		do {
			// cout << v << ": "; for(auto x : os) cout << x + dodane << " "; cout << "\n";
			for(ll idx : myq[v]) {
				ll czas = queries[idx].t;
				/*ll ile = max(0LL, czas-(*os.rbegin())-dodane) / okres;
				czas -= ile*okres;
				ans[idx] = ile * os.size() + os.order_of_key(czas-dodane+1);*/
				for(auto x : os) {
					ll val = x + dodane;
					if(val <= czas) ans[idx] += (czas-val)/okres + 1;
				}
			}
			auto[u,c] = next[v];
			for(auto x : subTree[v]) os.erase(x-dodane);
			for(auto x : subTree[v]) os.insert(x+okres-dodane);
			dodane -= c;
			v = u;
		} while(v!=start);
	}
	for(ll i=0; i<q; ++i) cout << ans[i] << "\n";

	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...