QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#821413#4417. Shallow MoonjiamengtongAC ✓1510ms88420kbC++146.3kb2024-12-19 15:53:342024-12-19 15:53:38

Judging History

This is the latest submission verdict.

  • [2024-12-19 15:53:38]
  • Judged
  • Verdict: AC
  • Time: 1510ms
  • Memory: 88420kb
  • [2024-12-19 15:53:34]
  • Submitted

answer

#pragma GCC optimize(2,3,"inline","Ofast","unroll-loops")
#include<bits/stdc++.h>
#define int long long
#define M 1000005
using namespace std;
int n, m, w, h, a[M], b[M], tot, cnt, lst[M], num;
unsigned long long jmt[M];
struct node{
	int bl, st, op, ht;
}seq[M * 2];
bool cmp(node x, node y)
{
	return x.bl < y.bl;
}
struct Line{
	int ps, bd, op, ht;
}nseq[M * 2];
bool cmp1(Line x, Line y)
{
	return x.ps < y.ps;
}
struct Squ{
	int bl, x1, y1, x2, y2;
}squ[M * 2];
bool cmp2(Squ x, Squ y)
{
	if(x.bl != y.bl) return x.bl < y.bl;
	return x.y1 < y.y1;
}
multiset<int> s[2];
void mk(int l, int r)
{
	int top = 0, bl = seq[l].bl;
	lst[++num] = bl;
	for(int i = l; i <= r; i++)
	{
		int st = seq[i].st, op = seq[i].op, ht = seq[i].ht;
		nseq[++top] = {st, op, 0, ht};
		nseq[++top] = {st + h, op, 1, ht};
	}
//	cout << l << " " << r << " " << r - l + 1 << endl;
	sort(nseq + 1, nseq + top + 1, cmp1);
//	for(int i = 1; i <= top; i++) printf("%d %d %d %d\n", nseq[i].ps, nseq[i].bd, nseq[i].op, nseq[i].ht);
	int lst = 0;
//	if(nseq[1].ps > 0) squ[++cnt] = {bl, 0, 0, w - 1, nseq[1].ps - 1}, lst = nseq[1].ps;
//	s[0].clear(), s[1].clear();
	for(int i = 1; i <= top; i++)
	{
//		if(nseq[i].ps >= m)
//		{
//			lst = m;
//			break;
//		}
		int Ub = 0, Rb = 0;
		if(s[0].size()) Ub = *(s[0].rbegin());
		if(s[1].size()) Rb = *(s[1].rbegin());
		int lb = Ub, rb = w - 1 - Rb;
		if(bl == (m - 1) / w) rb = (m - 1) % w + 1 - 1 - Rb;
		if(lb <= rb && nseq[i].ps > lst) squ[++cnt] = {bl, lb, lst, rb, nseq[i].ps - 1};
		int j = i;
		while(j < top && nseq[j + 1].ps == nseq[i].ps) j++;
		for(int k = i; k <= j; k++)
		{
			int bd = nseq[k].bd, op = nseq[k].op, ht = nseq[k].ht;
			if(!op) s[bd].insert(ht);
			else s[bd].erase(s[bd].find(ht));
		}
//		cout << "NOW: " << i << " " << j << " " << Ub << " " << Rb << endl;
//		int lb = bl * w + Ub, rb = (w - ((m - 1) / w - bl) * w - 1 - Rb);
//		int lb = Ub, rb = w - 1 - Rb;
//		if(bl == (m - 1) / w) rb = (m - 1) % w + 1 - 1 - Rb;
//		if(lb <= rb) squ[++cnt] = {bl, lb, lst, rb, nseq[i].ps};// cout << "ADD: " << bl << " " << lb << " " << lst << " " << rb << " " << nseq[i].ps << endl;
		lst = nseq[i].ps;
		i = j;
	}
	if(lst < m)
	{
//		int lb = bl * w, rb = (w - ((m - 1) / w - bl) * w - 1);
		int rb = w - 1;
		if(bl == (m - 1) / w) rb = (m - 1) % w;
		squ[++cnt] = {bl, 0, lst, rb, m - 1};
	}
}
int fa[M * 2];
int find(int x)
{
	return ((fa[x] == x) ? x : (fa[x] = find(fa[x])));
}
void merge(int x, int y)
{
	int fx = find(x), fy = find(y);
	if(fx == fy) return;
	fa[fx] = fy;
}
void add(int l, int r)
{
	for(int i = l; i < r; i++)
	{
//		cout << squ[i].y2 << " " << squ[i + 1].y1 - 1 << endl; 
		if(squ[i].y2 == squ[i + 1].y1 - 1 && min(squ[i].x2, squ[i + 1].x2) >= max(squ[i].x1, squ[i + 1].x1)) merge(i, i + 1);
	}
}
struct Segment{
	int l, r, id;
}ls[M * 2], rs[M * 2];
bool cmp3(Segment x, Segment y)
{
	return x.l < y.l;
}
void Add(int l, int r, int L, int R)
{
	if(squ[l].x2 < w && squ[L].x2 < w)
	{
		if(squ[l].bl != squ[L].bl - 1) return;
	}
	else
	{
		if(squ[l].x2 < w)
		{
			if(squ[l].bl != squ[L].bl - 1) return;
		}
		else
		{
			if(squ[l].bl + (squ[l].x2 - squ[l].x1 + 1) / w != squ[L].bl) return;
		}
	}
	int ltot = 0, rtot = 0;
	for(int i = l; i <= r; i++) if(squ[i].x2 % w == w - 1) ls[++ltot] = {squ[i].y1, squ[i].y2, i};
	for(int i = L; i <= R; i++) if(squ[i].x1 % w == 0) rs[++rtot] = {squ[i].y1, squ[i].y2, i};
	sort(ls + 1, ls + ltot + 1, cmp3);
	sort(rs + 1, rs + rtot + 1, cmp3);
	int i = 1, j = 1;
//	for(int i = 1; i <= ltot; )
	while(i <= ltot && j <= rtot)
	{
//		cout << l << " " << r << " " << i << " " << j << " " << max(ls[i].l, rs[j].l) << " " << min(ls[i].r, rs[j].r) << endl; 
		if(max(ls[i].l, rs[j].l) <= min(ls[i].r, rs[j].r)) merge(ls[i].id, rs[j].id);
		if(i == ltot) j++;
		else if(j == rtot) i++;
		else if(ls[i + 1].l < rs[j + 1].l) i++;
		else j++;
	}
//	for(int i = 1; i <= ltot; i++) for(int j = 1; j <= rtot; j++) if(max(ls[i].l, rs[j].l) <= min(ls[i].r, rs[j].r)) merge(ls[i].id, rs[j].id);// cout << ls[i].id << " " << rs[j].id << endl;
}
void print(__int128 x)
{
	if(x <= 9) return putchar('0' + x), void();
	print(x / 10);
	putchar('0' + x % 10);
}
void solve()
{
	scanf("%lld%lld%lld%lld", &n, &m, &w, &h);
	for(int i = 1; i <= n; i++)
	{
		scanf("%lld%lld", &a[i], &b[i]), a[i]--, b[i]--;
		seq[++tot] = {a[i] / w, b[i], 1, w - a[i] % w};
		seq[++tot] = {(a[i] + w - 1) / w, b[i], 0, a[i] % w};
	}
	sort(seq + 1, seq + tot + 1, cmp);
	lst[++num] = -1;
	for(int i = 1; i <= tot; i++)
	{
		int j = i;
		while(j < tot && seq[j + 1].bl == seq[i].bl) j++;
		mk(i, j);
		i = j;
	}
	lst[++num] = (m - 1) / w + 1;
	for(int i = 2; i <= num; i++) if(lst[i] - lst[i - 1] > 1) squ[++cnt] = {lst[i - 1] + 1, (lst[i - 1] + 1) * w, 0, min(lst[i] * w - 1, m - 1), m - 1};
	sort(squ + 1, squ + cnt + 1, cmp2);
//	for(int i = 1; i <= cnt; i++) printf("%d %d %d %d %d\n", squ[i].bl, squ[i].x1, squ[i].y1, squ[i].x2, squ[i].y2);
	for(int i = 1; i <= cnt; i++) fa[i] = i;
	for(int i = 1; i <= cnt; i++)
	{
		int j = i;
		while(j < cnt && squ[j + 1].bl == squ[i].bl) j++;
//		cout << i << " " << j << endl;
		add(i, j);
		i = j;
	}
//	for(int i = 1; i <= cnt; i++) printf("%d ", find(i));
//	puts("");
	for(int i = 1; i <= cnt; i++)
	{
		int j = i;
		while(j < cnt && squ[j + 1].bl == squ[i].bl) j++;
//		cout << i << " " << j << endl;
		if(j == cnt) break;
//		cout << i << " " << j << endl; 
		int j1 = j + 1;
		while(j1 < cnt && squ[j1 + 1].bl == squ[j1].bl) j1++;
//		cout << i << " " << j << " " << j + 1 << " " << j1 << endl;
		Add(i, j, j + 1, j1);
		i = j;
	}
//	for(int i = 1; i <= cnt; i++) printf("%d ", find(i));
//	puts("");
//	for(int i = 1; i <= cnt; i++) printf("%d %d %d %d %d\n", squ[i].bl, squ[i].x1, squ[i].y1, squ[i].x2, squ[i].y2);
	for(int i = 1; i <= cnt; i++) jmt[find(i)] += (squ[i].x2 - squ[i].x1 + 1) * (squ[i].y2 - squ[i].y1 + 1);// cout << (squ[i].x2 - squ[i].x1 + 1) * (squ[i].y2 - squ[i].y1 + 1) << endl;
	unsigned long long ans = 0;
	for(int i = 1; i <= cnt; i++) ans += jmt[i] * jmt[i], jmt[i] = 0;
	printf("%llu\n", ans);
//	print(ans);
//	putchar('\n');
	cnt = 0;
	num = 0;
	tot = 0;
}
signed main()
{
//	freopen("G.in", "r", stdin);
//	freopen("data.in", "r", stdin);
//	freopen("std.out", "w", stdout);
	int T;
	scanf("%lld", &T);
	while(T--) solve();
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1510ms
memory: 88420kb

input:

501
1000 1000000000 8 6
196705452 282810113
937875223 275529064
629271205 864549686
750495261 246485461
543433237 255456903
488123456 624378383
54011768 202210239
202279514 480198740
310520275 178661688
643456981 428672131
21485303 109706962
473119724 616638896
589883353 354364583
907646968 63640664...

output:

9775754433921302528
12719218429090003200
3102866340934553600
1731322551472548096
9775754433921302528
12518842016069313536
1900607941410415616
17573173619913134080
621479607805049408
16047889703994672128
9451871597547151424
15246384117911913472
3393948179234228288
15136715046354208832
122709744547405...

result:

ok 501 lines