社区讨论

有无卡常大神

P9755[CSP-S 2023] 种树参与者 7已保存回复 22

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
22 条
当前快照
1 份
快照标识符
@mhjbczf4
此快照首次捕获于
2025/11/03 23:47
4 个月前
此快照最后确认于
2025/11/04 06:10
4 个月前
查看原帖
需要一些比较正经的卡常/bx
CPP
#include <bits/stdc++.h>
using lint = long long;
using pii = std::pair<int, int>;
const int N = 1e5 + 10;

// #define DEBUG 1  // 调试开关
struct IO {
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
  char buf[MAXSIZE], *p1, *p2;
  char pbuf[MAXSIZE], *pp;
#if DEBUG
#else
  IO() : p1(buf), p2(buf), pp(pbuf) {}

  ~IO() { fwrite(pbuf, 1, pp - pbuf, stdout); }
#endif
  char gc() {
#if DEBUG  // 调试,可显示字符
    return getchar();
#endif
    if (p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
    return p1 == p2 ? ' ' : *p1++;
  }

  void read(int &x) {
    bool neg = false;
    x = 0;
    char ch = gc();
    for (; !isdigit(ch); ch = gc())
      if (ch == '-') neg = true;
    if (neg)
      for (; isdigit(ch); ch = gc()) x = x * 10 + ('0' - ch);
    else
      for (; isdigit(ch); ch = gc()) x = x * 10 + (ch - '0');
  }
  
  void read(long long &x) {
    bool neg = false;
    x = 0;
    char ch = gc();
    for (; !isdigit(ch); ch = gc())
      if (ch == '-') neg = true;
    if (neg)
      for (; isdigit(ch); ch = gc()) x = x * 10 + ('0' - ch);
    else
      for (; isdigit(ch); ch = gc()) x = x * 10 + (ch - '0');
  }

  void read(char *s) {
    char ch = gc();
    for (; isspace(ch); ch = gc());
    for (; !isspace(ch); ch = gc()) *s++ = ch;
    *s = 0;
  }

  void read(char &c) { for (c = gc(); isspace(c); c = gc()); }

  void push(const char &c) {
#if DEBUG  // 调试,可显示字符
    putchar(c);
#else
    if (pp - pbuf == MAXSIZE) fwrite(pbuf, 1, MAXSIZE, stdout), pp = pbuf;
    *pp++ = c;
#endif
  }

  void write(int x) {
    bool neg = false;
    if (x < 0) {
      neg = true;
      push('-');
    }
    static int sta[40];
    int top = 0;
    do {
      sta[top++] = x % 10;
      x /= 10;
    } while (x);
    if (neg)
      while (top) push('0' - sta[--top]);
    else
      while (top) push('0' + sta[--top]);
  }

  void write(int x, char lastChar) { write(x), push(lastChar); }
} io;

struct Tree {
	int id;
	lint a, b, c;
	int lst;
	int mx; // 子树中的最小 lst 
	
	bool operator<(const Tree &x) const {
		if (mx != x.mx) return mx > x.mx;
		if (lst != x.lst) return lst > x.lst;
		if (id != x.id) return id < x.id;
		if (a != x.a) return a < x.a;
		if (b != x.b) return b < x.b;
		return c < x.c;
	}
} t[N];

bool vis[N];
std::vector<int> g[N];
int n, s[N];

__int128 f(lint u, lint x, int i) {
	if (u > x) return 0;
	lint b = t[i].b, c = t[i].c;
	
	if (c >= 0) {
		return (__int128)(x - u + 1) * b + (__int128)(u + x) * (x - u + 1) / 2 * c;
	}
	
	lint p =  (1 - b) / c;
	if (p >= x) return (__int128)(x - u + 1) * b + (__int128)(u + x) * (x - u + 1) / 2 * c;
	else if (u > p) return x - u + 1;
	return (__int128)(p - u + 1) * b + (__int128)(u + p) * (p - u + 1) / 2 * c + x - p;
}

void calc(int i, lint x) {
	lint l = 0, r = 1e9 + 1;
	while (l + 1 != r) {
		lint mid = (l + r) >> 1;
		if (f(mid, x, i) >= t[i].a) l = mid;
		else r = mid;
	}
	t[i].lst = l;
}

void dfs(int u, int f) {
	t[u].mx = t[u].lst;
	for (auto v : g[u]) {
		if (v == f) continue;
		dfs(v, u);
		t[u].mx = std::min(t[u].mx, t[v].mx);
	}
}

bool check(lint x) { // x 天内能否完成
	for (int i = 1; i <= n; ++i) {
		calc(i, x);
		if (t[i].lst < 1) return false;
	}
	
	dfs(1, 1);
	
	memset(vis, 0, sizeof(vis));
	
	std::priority_queue<Tree> heap;
	heap.push(t[1]), vis[1] = true;
	int cnt = 0;
	while (heap.size()) {
		auto cur = heap.top(); heap.pop();
		s[cur.id] = ++cnt;
		for (auto v : g[cur.id]) {
			if (!vis[v]) {
				heap.push(t[v]);
				vis[v] = true;
			}
		}
	}
	for (int i = 1; i <= n; ++i)
		if (s[i] > t[i].lst) return false;
	return true;
}

signed main() {
	io.read(n);
	for (int i = 1; i <= n; ++i) {
		io.read(t[i].a), io.read(t[i].b), io.read(t[i].c);
		t[i].id = i;
	}
	for (int i = 1, u , v; i < n; ++i) {
		io.read(u), io.read(v);
		g[u].emplace_back(v);
		g[v].emplace_back(u);
	}
	lint l = 0, r = 1e9 + 1;
	while (l + 1 != r) {
		lint mid = (l + r) >> 1;
		if (check(mid)) r = mid;
		else l = mid;
	}
	io.write(r, '\n');
  return 0;
}

回复

22 条回复,欢迎继续交流。

正在加载回复...