QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#821413 | #4417. Shallow Moon | jiamengtong | AC ✓ | 1510ms | 88420kb | C++14 | 6.3kb | 2024-12-19 15:53:34 | 2024-12-19 15:53:38 |
Judging History
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