답안 #799891

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
799891 2023-08-01T07:39:03 Z 박상훈(#10082) 수확 (JOI20_harvest) C++17
0 / 100
5000 ms 20052 KB
#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef long long ll;

constexpr int MAXN = 200200;

int n, m, q, cnti, cntj;
ll L, c;
ll a[MAXN], b[MAXN];

vector<int> adj[MAXN], buf[MAXN];

int go[MAXN], f[MAXN], tmpf[MAXN], top[MAXN], visited[MAXN], inj[MAXN], outj[MAXN], comp[MAXN], typ[MAXN], ord[MAXN];
ll W[MAXN], s[MAXN], tmps[MAXN], g[MAXN], ofs[MAXN], ans[MAXN], T[MAXN], dp[MAXN];

struct Query{
	int v;
	ll t;
	int i;

	Query(){}
	Query(int _v, ll _t, int _i): v(_v), t(_t), i(_i) {}
}Q[MAXN];


inline ll mydiv(ll x, ll y){
	ll ret = x / y;
	if (ret*y > x) return ret-1;
	return ret;
}

inline ll mymod(ll x, ll y){
	ll ret = x % y;
	if (ret < 0) return ret + y;
	return ret;
}

void dfs(int s, int root, int root2, int pa){
	visited[s] = 2;
	comp[s] = root;
	
	if (pa > 0) dp[s] = dp[pa] + W[s];
	else dp[s] = 0;

	inj[s] = cntj;
	
	for (auto &j:buf[s]){
		f[cntj] = tmpf[j];
		::s[cntj] = tmps[j];
		top[cntj] = root2;

		g[cntj] = -::s[cntj]-dp[f[cntj]]+ofs[root2];
		g[cntj] = -g[cntj];

		// printf(" j = %lld (cntj = %lld) -> s = %lld / cyc = %lld / g = %lld\n", j, cntj, ::s[cntj], ::s[cntj]+dp[f[cntj]], g[cntj]);
		
		cntj++;
	}

	for (auto &v:adj[s]) dfs(v, root, root2, s);

	outj[s] = cntj-1;
}

void init(){
	cnti = cntj = 1;

	// init go, W, adj
	for (int i=1;i<=n;i++){
		ll nc = c % L, quo = c / L;
		if (a[i]-a[1] < nc){
			go[i] = upper_bound(a+i+1, a+n+1, L+a[i]-nc) - a - 1;
			W[i] = quo * L + L - (a[go[i]] - a[i]);
		}

		else{
			go[i] = upper_bound(a+1, a+i+1, a[i]-nc) - a - 1;
			W[i] = quo * L + a[i] - a[go[i]];
		}

		adj[go[i]].push_back(i);
	}

	// debug
	// printf(" ok1\n");
	
	// printf("go: ");
	// for (int i=1;i<=n;i++) printf("%lld ", go[i]);
	// printf("\n");

	// printf("W: ");
	// for (int i=1;i<=n;i++) printf("%lld ", W[i]);
	// printf("\n");

	// push j
	for (int j=1;j<=m;j++){
		tmpf[j] = upper_bound(a+1, a+n+1, b[j]) - a - 1;

		if (tmpf[j]==0){
			tmpf[j] = n;
			tmps[j] = L - (a[n] - b[j]);
		}

		else{
			tmps[j] = b[j] - a[tmpf[j]];
		}

		buf[tmpf[j]].push_back(j);

	}

	// printf(" ok2\n");

	// get component info
	for (int i=1;i<=n;i++) if (!visited[i]){
		int root = -1;
		for (int s=i;;s=go[s]){
			if (visited[s]==1){root = s; break;}
			visited[s] = 1;
		}

		assert(root!=-1);
		ofs[root] = 0;

		for (int s=root;;s=go[s]){
			ord[s] = cnti++;
			typ[s] = 1;
			
			auto iter = find(adj[go[s]].begin(), adj[go[s]].end(), s);
			assert(iter!=adj[go[s]].end());
			adj[go[s]].erase(iter);

			if (go[s]==root){
				T[root] = ofs[s] + W[s];
				break;
			} 
			ofs[go[s]] = ofs[s] + W[s];
		}

		inj[root] = cntj;

		for (int s=root;;s=go[s]){
			dfs(s, root, s, 0);

			if (go[s]==root) break;
		}

		outj[root] = cntj-1;
	}

	
	
	// printf("comp: ");
	// for (int i=1;i<=n;i++) printf("%lld ", comp[i]);
	// printf("\n");

	// printf("typ: ");
	// for (int i=1;i<=n;i++) printf("%lld ", typ[i]);
	// printf("\n");

	// printf("in/out: ");
	// for (int i=1;i<=n;i++) printf("(%lld, %lld) ", inj[i], outj[i]);
	// printf("\n");

}

void naive(){
	for (int _=1;_<=q;_++){
		auto [v, t, i] = Q[_];
		ll ret = 0;

		if (typ[v]==0){ // tree
			// printf(" query %lld: tree\n", i);
			for (int j=inj[v];j<=outj[v];j++){
				if (t + dp[v] >= s[j] - dp[f[j]]) ret++;
			}
		}

		else{ // cycle
			// printf(" query %lld: cycle\n", i);
			int idx = comp[v];

			for (int j=inj[idx];j<=outj[idx];j++) if (t-ofs[v] >= g[j]){
				ret++;
				ret += mydiv((t-ofs[v]), T[idx]) - mydiv(g[j], T[idx]) - (mymod((t-ofs[v]), T[idx]) < mymod(g[j], T[idx]));

				// ret += (t-ofs[v]-g[j]) / T[idx] + 1;

				// printf("ok ret = %lld\n", ret);

				if (ord[v] < ord[top[j]]) ret--;

				// printf("ok ret = %lld\n\n", ret);
			}
		}

		ans[i] = ret;
	}
}

signed main(){
	scanf("%lld %lld %lld %lld", &n, &m, &L, &c);
	for (int i=1;i<=n;i++) scanf("%lld", a+i);
	for (int i=1;i<=m;i++) scanf("%lld", b+i);

	scanf("%lld", &q);
	for (int i=1;i<=q;i++){
		scanf("%lld %lld", &Q[i].v, &Q[i].t);
		Q[i].i = i;
	}

	init();
	naive();

	for (int i=1;i<=q;i++) printf("%lld\n", ans[i]);
}

Compilation message

harvest.cpp: In function 'int main()':
harvest.cpp:204:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  204 |  scanf("%lld %lld %lld %lld", &n, &m, &L, &c);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
harvest.cpp:205:30: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  205 |  for (int i=1;i<=n;i++) scanf("%lld", a+i);
      |                         ~~~~~^~~~~~~~~~~~~
harvest.cpp:206:30: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  206 |  for (int i=1;i<=m;i++) scanf("%lld", b+i);
      |                         ~~~~~^~~~~~~~~~~~~
harvest.cpp:208:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  208 |  scanf("%lld", &q);
      |  ~~~~~^~~~~~~~~~~~
harvest.cpp:210:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  210 |   scanf("%lld %lld", &Q[i].v, &Q[i].t);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 6 ms 10020 KB Output is correct
2 Correct 6 ms 10580 KB Output is correct
3 Correct 125 ms 10624 KB Output is correct
4 Incorrect 7 ms 10580 KB Output isn't correct
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 5066 ms 20052 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 6 ms 10020 KB Output is correct
2 Correct 6 ms 10580 KB Output is correct
3 Correct 125 ms 10624 KB Output is correct
4 Incorrect 7 ms 10580 KB Output isn't correct
5 Halted 0 ms 0 KB -