제출 #1328346

#제출 시각아이디문제언어결과실행 시간메모리
1328346vlomaczk수확 (JOI20_harvest)C++20
0 / 100
90 ms56600 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>;

template <typename TY>
struct MultiOrderedSet {
	ordered_set<pair<TY, int>> os;
	int cnt = 0;
	void insert(TY x) {
		os.insert({x, cnt++});
	}
	void erase(TY x) {
		int idx = os.order_of_key({x,-1});
		assert(idx < os.size());
		os.erase(*os.find_by_order(idx));
	}
	TY first() { return os.begin()->first; }
	TY last() { return os.rbegin()->first; }
	void clear() {
		while(os.size()) os.erase(*os.begin());
	}
	int size() { return os.size(); }
	bool empty() { return os.empty(); }
	int order_of_key(TY x) {
		return os.order_of_key({x, -1});
	}
	TY find_by_order(ll x) {
		return os.find_by_order(x)->first;
	}
};

struct Query {
	ll v, t, i;
};

ll M = 200'010;
vector<vector<pair<ll, ll>>> g(M);
vector<vector<ll>> mine(M);
vector<pair<ll, ll>> nxt(M, {-1, 0}), cykl(M, {-1, 0});
vector<ll> depth(M), vis(M), ans(M), root(M), roots, P(M, 0), on_cycle(M), path;
vector<Query> queries(M);

void meduza_dfs(ll v) {
	path.push_back(v);
	vis[v] = 1;
	auto[u,d] = nxt[v];
	if(vis[u]==2) {
		root[v] = root[u];
		vis[v] = 2;
	} else if(vis[u]==1) {
		P[v] = depth[v] - depth[u] + d;
		root[v] = v;
		roots.push_back(v);
		
		ll idx = path.size()-1;
		while(path[idx] != u) {
			on_cycle[path[idx]] = 1;
			idx--;
		}
		on_cycle[u] = 1;

		cykl[v] = nxt[v];
		nxt[v].first = -1;
	} else {
		depth[u] = depth[v] + d;
		meduza_dfs(u);
		root[v] = root[u];
	}
	vis[v] = 2;
	path.pop_back();
}

ll base = 1<<19;
vector<ll> 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;
}

ll cnt = 1;
vector<ll> pre(M), post(M);

void pre_dfs(ll v) {
	pre[v] = cnt++;	
	for(auto[u,k] : g[v]) {
		depth[u] = depth[v] + k;
		pre_dfs(u);
	}
	post[v] = cnt++;
}

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> ludzie(n), jablka(m);
	for(ll i=0; i<n; ++i) cin >> ludzie[i];
	for(ll i=0; i<m; ++i) cin >> jablka[i];
	ll q; cin >> q;
	for(ll i=0; i<q; ++i) {
		ll v, t;
		cin >> v >> t;
		queries[i] = {v-1, t, i};
	}
	auto dist = [&](ll a, ll b) {
		if(a<=b) return b-a;
		else return L + b - a;
	};
	auto dist_emp = [&](ll x, ll y) {
		if(x==y) return L;
		return dist(ludzie[x], ludzie[y]);
	};
	ll Pan = n-1;
	ll idx = 0;
	for(ll i=0; i<m; ++i) {
		while(idx < n && ludzie[idx] <= jablka[i]) {
			Pan = idx;
			idx++;
		}
		mine[Pan].push_back(dist(ludzie[Pan], jablka[i]));
	}
	for(ll i=0; i<n; ++i) sort(mine[i].begin(), mine[i].end());
	ll iterator = 0;
	ll cl = (C%L ? C%L : L);
	ll d_it = 0;
	ll d_mine = L;
	for(ll i=0; i<n; ++i) {
		int d_nxt = dist_emp(iterator, (iterator+1)%n);
		while(d_mine - (d_it + d_nxt) >= cl) {
			iterator = (iterator+1)%n;
			d_it += d_nxt;
			d_nxt = dist_emp(iterator, (iterator+1)%n);
		}
		ll D = d_mine - d_it;
		if(C > L) {
			if(cl!=L) D += L*(C/L);
			else D += L*(C/L) - L;
		}
		nxt[i] = {iterator, D};
		d_mine += dist_emp(i, (i+1)%n);
	}
	for(ll i=0; i<n; ++i) if(!vis[i]) meduza_dfs(i);
	for(ll i=0; i<n; ++i) if(nxt[i].first!=-1) g[nxt[i].first].push_back({i, nxt[i].second});
	for(auto r : roots) {
		depth[r] = 0;
		pre_dfs(r);
	}
	vector<vector<pair<ll, ll>>> zap1(n); // zap1[v][..] = {T, q_idx}
	vector<pair<ll, pair<ll, ll>>> zap2; // zap2[..] = {T + depth, {q_idx, v}}
	for(ll idx=0; idx<q; ++idx) {
		auto[v,t,i] = queries[idx];
		zap2.push_back({t + depth[v], {i, v}});
		if(on_cycle[v]) {
			if(t >= P[root[v]]-depth[v]) zap1[root[v]].push_back({t-P[root[v]]+depth[v], i});
		}
	}
	for(ll i=0; i<n; ++i) {
		for(auto a : mine[i]) zap2.push_back({a + depth[i], {-1, i}}); 
	}

	sort(zap2.begin(), zap2.end());
	for(auto[T, stat] : zap2) {
		auto[q_idx, v] = stat;
		if(q_idx==-1) update(pre[v], 1);
		else ans[q_idx] += query(pre[v], post[v]);
	}
	vector<vector<ll>> child(n);
	for(ll i=0; i<n; ++i) {
		for(auto a : mine[i]) {
			child[root[i]].push_back(a + depth[i]);
		}
	}
	for(auto r : roots) {
		sort(child[r].begin(), child[r].end());
		vector<int> prefix(child[r].size()+1);
		vector<vector<pair<int, int>>> quer(child[r].size()+1);
		ll D = P[r];
		for(int i=1; i<=child[r].size(); ++i) prefix[i] = prefix[i-1] + (child[r][i-1]/D);
		for(auto[T, q_idx] : zap1[r]) {
			ll res = 0;
			int ile = upper_bound(child[r].begin(), child[r].end(), T) - child[r].begin();
			if(!ile) continue;
			ans[q_idx] += ile * (T/D);
			ans[q_idx] -= prefix[ile];
			quer[ile].push_back({T%D, q_idx});
		} 	
		MultiOrderedSet<ll> os;
		for(int i=0; i<n; ++i) {
			os.insert(child[r][i]%D);
			for(auto[x, q_idx] : quer[i+1]) {
				ans[q_idx] += os.order_of_key(x+1);
			} 
		}
	}
 	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...