萌新刚学 OI, 求调权值线段树维护 CDQ
查看原帖
萌新刚学 OI, 求调权值线段树维护 CDQ
374500
AtomAlpaca楼主2023/4/13 15:51

TLE 50pts, 盲猜是因为线段树常数大

#include <bits/stdc++.h>

using std::cin;
using std::cout;

const int MAX = 1e5 + 5;

int n, mx, m;
int rt[(MAX << 4) + 5], ans[(MAX << 1) + 5];

struct N
{
	int a, b, c, cnt, ans;
	bool operator != (N x)
	{
		return (a != x.a or b != x.b or c != x.c);
	}
} a[MAX], b[MAX];

bool cmpB(N n1, N n2)
{
	if (n1.b == n2.b) { return n1.c < n2.c; }
	return n1.b < n2.b;
}

bool cmpA(N n1, N n2)
{
	if (n1.a == n2.a) { return cmpB(n1, n2); }
	return n1.a < n2.a;
}

void add(int l, int r, int s, int v, int x)
{
	if (l == r and l == s) { rt[x] += v; return ; }
	int k = l + ((r - l) >> 1);
	if (s <= k) { add(l, k, s, v, x << 1); }
	else 		{ add(k + 1, r, s, v, x << 1 | 1); }
	rt[x] = rt[x << 1] + rt[x << 1 | 1];
}

int get(int l, int r, int s, int t, int x)
{
	if (l >= s and r <= t) { return rt[x]; }
	int k = l + ((r - l) >> 1), tmp = 0;
	if (k >= s) { tmp += get(l, k, s, t, x << 1); }
	if (k < t)  { tmp += get(k + 1, r, s, t, x << 1 | 1); }
	return tmp;
}

void clear(int l, int r, int x)
{
	rt[x] = 0;
	if (l == r) { return ; }
	int k = l + ((r - l) >> 1);
	clear(l, k, x << 1);
	clear(k + 1, r, x << 1 | 1);
}

void cdq(int l, int r)
{
	if (l == r) { return ; }
	int k = l + ((r - l) >> 1);
	cdq(l, k); cdq(k + 1, r);
	std::sort(b + l, b + k + 1, cmpB);
	std::sort(b + k + 1, b + r + 1, cmpB);
	int i = l, j = k + 1;
	while (j <= r)
	{
		while (i <= k)
		{
			if (b[i].b <= b[j].b) { add(1, mx, b[i].c, b[i].cnt, 1); }
			else 				  { break; }
			++i;
		}
		b[j].ans += get(1, mx, 1, b[j].c, 1);
		++j;
	}
	clear(1, mx, 1);
}

int main()
{
	cin.tie(NULL);
	cout.tie(NULL);
	std::ios::sync_with_stdio(false);

	cin >> n >> mx;
	for (int i = 1; i <= n; ++i) { cin >> a[i].a >> a[i].b >> a[i].c; }
	std::sort(a + 1, a + n + 1, cmpA);
	int tmp = 0;
	for (int i = 1; i <= n; ++i)
	{
		++tmp;
		if (a[i] != a[i + 1])
		{
			++m;
			b[m] = {a[i].a, a[i].b, a[i].c, tmp, 0};
			tmp = 0;
		}
	}
	cdq(1, m);
	for (int i = 1; i <= m; ++i) { ans[b[i].ans + b[i].cnt - 1] += b[i].cnt; }
	for (int i = 0; i <  n; ++i) { cout << ans[i] << '\n'; }
	return 0;
}

2023/4/13 15:51
加载中...