bsdsdb's blog

By bsdsdb, 10 months ago, In English

That was the way I used to build a centroid tree (a tree that connects all the adjacent centroids during centroid decomposition, used in 342E - Xenia and Tree):

That

Then I found there were too many for (ll i : e[x]) if (i == pr || vis[i]) continue;s, so I used a macro to do shorten them:

them

This reduces my code for about 150 bytes. But what I'm worrying now is: will macros increase the difficulty to debug my code, especially in some on-site contests, where templates are not allowed?

I also used #define mid ((lx+rx)>>1) #define l(x) ((x)<<1) #define r(X) (l(x)|1) in segment tree for months btw

Full text and comments »

  • Vote: I like it
  • +14
  • Vote: I do not like it

By bsdsdb, history, 13 months ago, In English

can do almost any 2200* in problemset, but not in a contest, what should i do

Full text and comments »

  • Vote: I like it
  • +27
  • Vote: I do not like it

By bsdsdb, history, 15 months ago, In English

627C - Package Delivery

code:

#include <bits/stdc++.h>
using namespace std;
#define emp emplace
#define empb emplace_back
#define umap unordered_map
#define mkp make_pair
typedef long long ll;
typedef pair<ll, ll> pll;
const ll inf = 0x3f3f3f3f3f3f3f3fll;
typedef long double ldb;
const ll MAXN = 5e5 + 5;
mt19937_64 rd(chrono::high_resolution_clock().now().time_since_epoch().count());

#pragma GCC optimize(1,2,3,"Ofast","inline")

istream& operator>>(istream& in, __int128& x) {
	string s;
	in >> s;
	x = 0;
	for (char c : s) {
		x = x * 10 + c - 48;
	}
	return in;
}
ostream& operator<<(ostream& out, __int128 x) {
	if (!x) {
		out << "0";
		return out;
	}
	stack<char> s;
	while (x) {
		s.emp(x % 10 + 48);
		x /= 10;
	}
	while (!s.empty()) {
		out << s.top();
		s.pop();
	}
	return out;
}

struct segtree {
	ll V, l[MAXN], r[MAXN], fr[MAXN], mn[MAXN], rt, size;
	void init(ll x) {
		V = x;
		memset(l, 0, sizeof l);
		memset(r, 0, sizeof r);
		memset(fr, -1, sizeof fr);
		memset(mn, inf, sizeof mn);
		rt = 0;
		size = 0;
	}
	#define mid ((lx+rx)>>1)
	void psu(ll x) {
		if (mn[l[x]] <= mn[r[x]]) fr[x] = fr[l[x]], mn[x] = mn[l[x]];
		else fr[x] = fr[r[x]], mn[x] = mn[r[x]];
	}
	void mdf(ll p, ll v, ll& x, ll lx, ll rx) {
		if (p < lx || p > rx) return;
		if (!x) x = ++size;
		if (lx == rx) {
			fr[x] = p, mn[x] = v;
			return;
		}
		mdf(p, v, l[x], lx, mid), mdf(p, v, r[x], mid + 1, rx);
		psu(x);
	}
	void mdf(ll p, ll v) {mdf(p, v, rt, 0, V);}
	pll get(ll lb, ll rb, ll x, ll lx, ll rx) {
		if (!x) return mkp(-1, inf);
		if (lb <= lx && rx <= rb) return mkp(fr[x], mn[x]);
		auto lq = get(lb, rb, l[x], lx, mid), rq = get(lb, rb, r[x], mid + 1, rx);
		if (lq.second <= rq.second) return lq;
		return rq;
	}
	pll get(ll l, ll r) {return get(l, r, rt, 0, V);}
} st;;

ll p[MAXN], w[MAXN], d, g, n;

pll slv(ll l, ll r, ll yl) {
	if (r - l + 1 <= yl - 1) return mkp(-1, 0);
	pll ch = st.get(l, r);
	pll lq = slv(l, ch.first - 1, yl), rq = slv(ch.first + 1, r, g);
	ll jy = r + 1 - ch.first - (lq.first == -1) * (yl - ch.first);
	return mkp(lq.first == -1 ? ch.first : lq.first, lq.second + jy * ch.second + rq.second);
}

vector<ll> wj = {0};

int main() {
	cin >> d >> g >> n;
	st.init(d);
	for (ll i = 1; i <= n; ++i) cin >> p[i] >> w[i], st.mdf(p[i], w[i]), wj.empb(p[i]);
	wj.empb(d);
	sort(wj.begin(), wj.end());
	for (ll i = 1; i < wj.size(); ++i) if (wj[i] - wj[i - 1] > g) puts("-1"), exit(0);
	cout << slv(0, d - 1, g).second << endl;
	return 0;
}

isn't this segment tree + divide and conquer $$$\mathcal O(m\log d)$$$

Full text and comments »

  • Vote: I like it
  • -3
  • Vote: I do not like it

By bsdsdb, 15 months ago, In English
  • Vote: I like it
  • -4
  • Vote: I do not like it

By bsdsdb, 15 months ago, In English

442D - Adam and Tree

I hadn't mentioned the conclusion "brute force is $$$O(n\log n)$$$" at first. When i got the dp equation $$$\mathrm{dp}_x=\max(\mathrm{dp}_i,\mathrm{se}_x+1)$$$, where $$$i$$$ is a child of $$$x$$$, and $$$\mathrm{se}_x$$$ is the second maximum $$$\mathrm{dp}_i$$$, my first reaction is that the $$$\mathrm{dp}$$$-s updated in round $$$i$$$ is a path, started from $$$i$$$, and contained in the path $$$i$$$ to root. We can use a Link-Cut Tree (maybe without makeroot(x)? idk) to maintain that. But I don't know to maintain the following:

  • $$$\max\mathrm{dp}_i,\mathrm{se}_x$$$
  • $$$\mathrm{fr}_x$$$, which means where the $$$\max\mathrm{dp}_i$$$ is from
  • $$$\mathrm{stp}_x$$$, which means "when $$$\mathrm{dp}_x$$$ is updated (by 1), where should the update stop

when pushing up and pushing down. After maintaining that, we can simply use a lazy tag to do the dp update. Can anybody help?

Full text and comments »

Tags lct
  • Vote: I like it
  • +3
  • Vote: I do not like it

By bsdsdb, history, 17 months ago, In English

This is my solution for 2040E - Control of Randomness. It passed the tests, but I’m not sure whether deriving the DP formula in this way (splitting the min, solving the equation, and then putting the min back) is rigorous.

More formally, if we have $$$x_0$$$ is the only number that satisfies $$$x_0=f(x_0)$$$, and so do $$$x_1$$$ and $$$g(x_1)$$$, can we say that $$$x=h(f(x),g(x))\Leftrightarrow x=h(x_0,x_1)$$$? What if $$$h(x,y)=\min(x,y)$$$?

This (used ChatGPT to translate)
Solution (original Chinese ver)

Full text and comments »

  • Vote: I like it
  • +32
  • Vote: I do not like it

By bsdsdb, history, 18 months ago, In English

https://arxiv.org/pdf/2411.19826

Amazed by the perseverance, intellect, and exploratory spirit of mathematicians.

Full text and comments »

  • Vote: I like it
  • +39
  • Vote: I do not like it