Codeforces Round 974 (Div. 3)

EternalEpic發表於2024-09-22

拿小小號打的DIV3,中間看了會兒b站摸魚,結果尼瑪最後幾點鐘G沒寫完。。。

image

A. Robin Helps

模擬題

int T, n, k;

signed main(void) {
	for (read(T); T; T--) {
		read(n), read(k); int ans = 0; ll sum = 0;
		for (int i = 1; i <= n; i++) {
			int x; read(x);
			if (x >= k) sum += x;
			if (x == 0) {
				if (sum) sum--, ans++;
			}
		}
		writeln(ans);
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

B. Robin Hood and the Major Oak

根據mod4分類

int T, n, k;

signed main(void) {
	for (read(T); T; T--) {
		read(n), read(k);
		if (k % 4 == 0 || (k % 4 == 1 && n % 2 == 0) || (n % 2 == 1 && k % 4 == 3)) puts("YES");
		else puts("NO"); 
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

C. Robin Hood in Town

二分一下\(\Delta\)即可。

const int N = 2e5 + 5;
int T, n, k, a[N]; ll sum;

inline bool check(ll x) {
	int ret = 0;
	for (int i = 2; i <= n; i++)
		if (2ll * n * a[i] < sum + x) ++ret;
	if (ret * 2 > n) return true;
	return false;
}

signed main(void) {
	for (read(T); T; T--) {
		read(n); int mx = 0; sum = 0;
		for (int i = 1; i <= n; i++)
			read(a[i]), chkmax(mx, a[i]), sum += a[i];
		if (n == 1 || n == 2) { puts("-1"); continue; }
		sort(a + 1, a + n + 1, greater <int> ());
		ll l = 0, r = (ll) 1e18, ans = (ll) 1e18;
		while (l <= r) {
			ll mid = l + r >> 1;
			if (check(mid)) ans = mid, r = mid - 1;
			else l = mid + 1;
		}
		writeln(ans);
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

D. Robert Hood and Mrs Hood

用set模擬題意即可。

const int N = 1e5 + 10;
int n, d, k;
vector<int> l[N], r[N];

void slv() {
    cin >> n >> d >> k;
    for(int i = 1; i <= n; i++) l[i].clear(), r[i].clear();
    for(int i = 1; i <= k; i++) {
        int x, y;
        cin >> x >> y;
        l[x].push_back(i), r[y].push_back(i);
    }
    set<int> st;
    int ans1 = 0, ans2 = k + 1, ip1, ip2, pos = 1;
    for(int i = 1; i <= d; i++) {
        for(int ip : l[i]) st.insert(ip);
    }
    ans1 = ans2 = st.size(), ip1 = ip2 = 1;
    // cerr<<" pos= "<<1<<" siz="<<st.size()<<'\n';
    while(pos + 1 + d - 1 <= n) {
        for(int i : l[pos + 1 + d - 1]) st.insert(i);
        for(int i : r[pos]) st.erase(i);
        // cerr<<" pos= "<<pos+1<<" siz="<<st.size()<<'\n';
        if(ans1 < st.size()) ans1 = st.size(), ip1 = pos + 1;
        if(ans2 > st.size()) ans2 = st.size(), ip2 = pos + 1;
        pos++;
    }
    cout << ip1 << ' ' << ip2 << '\n';
    return;
}

E. Rendez-vous de Marian et Robin

跑兩遍分層圖最短路,列舉交點取最小的最大值即可。

struct Edge {
	int v, w;
	Edge(int v = 0, int w = 0) : v(v), w(w) {}
};

const int N = 2e5 + 5;
int T, n, m, h, a[N];
vector <Edge> G[N];

ll dis[N][2], f[N], g[N]; bool inq[N][2];
inline void DijkstraI(int s) {
	for (int i = 1; i <= n; i++) dis[i][0] = dis[i][1] = (ll) 1e18;
	priority_queue <piii, vector<piii>, greater<piii> > q;
	dis[s][0] = 0; q.push(Mpp(dis[s][0], s, 0)); Ms(inq, 0);
	if (a[s]) dis[s][1] = 0, q.push(Mpp(dis[s][1], s, 1));
	while (!q.empty()) {
		int u = q.top().second.first, id = q.top().second.second; q.pop();
		if (inq[u][id]) continue; inq[u][id] = true;
		for (auto x : G[u]) {
			int v = x.v, w = x.w;
			int e = id ? w / 2 : w;
			if (dis[v][id] > dis[u][id] + e) {
				dis[v][id] = dis[u][id] + e;
				if (!inq[v][id]) q.push(Mpp(dis[v][id], v, id));
			}
			if (a[v] && id == 0 && dis[v][1 - id] > dis[u][id] + e) {
				dis[v][1 - id] = dis[u][id] + e;
				if (!inq[v][1 - id]) q.push(Mpp(dis[v][1 - id], v, 1 - id));
			}
		}
	}
	for (int i = 1; i <= n; i++) f[i] = min(dis[i][1], dis[i][0]);
}

inline void DijkstraII(int s) {
	for (int i = 1; i <= n; i++) dis[i][0] = dis[i][1] = (ll) 1e18;
	priority_queue <piii, vector<piii>, greater<piii> > q;
	dis[s][0] = 0; q.push(Mpp(dis[s][0], s, 0)); Ms(inq, 0);
	if (a[s]) dis[s][1] = 0, q.push(Mpp(dis[s][1], s, 1));
	while (!q.empty()) {
		int u = q.top().second.first, id = q.top().second.second; q.pop();
		if (inq[u][id]) continue; inq[u][id] = true;
		for (auto x : G[u]) {
			int v = x.v, w = x.w;
			int e = id ? w / 2 : w;
			if (dis[v][id] > dis[u][id] + e) {
				dis[v][id] = dis[u][id] + e;
				if (!inq[v][id]) q.push(Mpp(dis[v][id], v, id));
			}
			if (a[v] && id == 0 && dis[v][1 - id] > dis[u][id] + e) {
				dis[v][1 - id] = dis[u][id] + e;
				if (!inq[v][1 - id]) q.push(Mpp(dis[v][1 - id], v, 1 - id));
			}
		}
	}
	for (int i = 1; i <= n; i++) g[i] = min(dis[i][1], dis[i][0]);
}

signed main(void) {
	for (read(T); T; T--) {
		read(n), read(m), read(h);
		for (int i = 1; i <= n; i++) G[i].clear(), a[i] = 0;
		for (int i = 1, x; i <= h; i++) read(x), a[x] = 1;
		for (int i = 1, u, v, w; i <= m; i++) {
			read(u), read(v), read(w);
			G[u].push_back(Edge(v, w));
			G[v].push_back(Edge(u, w));
		}
		DijkstraI(1); DijkstraII(n); ll ans = (ll) 1e18;
		for (int i = 1; i <= n; i++) {
			if (f[i] == (ll) 1e18 || g[i] == (ll) 1e18) continue;
			chkmin(ans, max(f[i], g[i]));
		}
		writeln(ans == (ll) 1e18 ? -1 : ans);
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

某個傻逼wa兩次的原因:
image

F. Sheriff's Defense

簡單樹形dp

const int N = 2e5 + 5;
int T, n, c, a[N];
vector <int> G[N];

ll dp[N][2];
inline void dfs(int u, int f) {
	dp[u][1] = a[u];
	for (auto v : G[u]) {
		if (v == f) continue;
		dfs(v, u);
		dp[u][0] += max(dp[v][0], dp[v][1]);
		dp[u][1] += max(dp[v][0], dp[v][1] - 2 * c);
	}
}

signed main(void) {
	for (read(T); T; T--) {
		read(n), read(c);
		for (int i = 1; i <= n; i++)
			read(a[i]), dp[i][0] = dp[i][1] = 0, G[i].clear();
		for (int i = 1, u, v; i < n; i++) {
			read(u), read(v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs(1, 0);
		writeln(max(dp[1][0], dp[1][1]));
	}
	//fwrite(pf, 1, o1 - pf, stdout);
	return 0;
}

G. Milky Days

傻逼雙端佇列模擬題,就是細節有點多。程式碼就不放了,懂得都懂。

H. Robin Hood Archery

本質是詢問一個區間裡所有出現的數是不是出現偶數次,可以一眼莫隊,也可以用隨機數加的異或字首和。

inline void slv(void) {
    cin >> n >> m;
    siz = sqrt(n);
    map<int, int> mp;
    int cnt = 0;
    for(int i = 1; i <= n; i++) {
        cin >> b[i];
        if(!mp[b[i]]) mp[b[i]] = ++cnt;
        b[i] = mp[b[i]];
    }
    s.clear(cnt);
    for(int i = 1; i <= m; i++) {
        cin >> a[i].l >> a[i].r;
        a[i].id = i;
        a[i].pos = (a[i].l - 1) / siz + 1;
    }
    sort(a + 1, a + 1 + m);
    int l = 1, r = 0;
    ll ans = 0;
    for(int i = 1; i <= m; i++) {
        while(l > a[i].l) s.ins(b[--l]);
        while(r < a[i].r) s.ins(b[++r]);
        while(l < a[i].l) s.del(b[l++]);
        while(r > a[i].r) s.del(b[r--]);
        res[a[i].id] = s.chk();
    }
    for(int i = 1; i <= m; i++)
        if(res[i]) cout << "YES\n";
        else cout << "NO\n";
    return;
}

相關文章