【题解】P4648 [IOI2007] pairs 动物对数
Problem#
给定模板
Solve#
#
考虑将问题化简成:求
然后考虑将一维坐标排序,枚举
时间复杂度
点击查看代码
namespace Solve1 {
int a[N], q[N], h = 1, t = 0, ans = 0;
void work() {
For(i,1,n) cin >> a[i];
sort(a + 1, a + n + 1);
For(i,1,n) {
while(t - h + 1 > 0 && a[i] - a[q[h]] > d) h++;
ans += (t - h + 1);
q[++t] = i;
}
cout << ans << '\n';
}
}
#
考虑降位。
第一维可以参考
但是我们注意到,答案贡献的领域是一个斜
所以我们只需要将曼哈顿距离转成且切比雪夫距离,这样答案贡献的领域就是一个正的,长度为
考虑如何转:
于是将原坐标
时间复杂度
点击查看代码
namespace Solve2 {
struct Node {
int x, y;
} a[N];
int q[N], h = 1, t = 0, Ans = 0;
Int T[N * 2] = {0};
bool cmp(Node x, Node y) {
return (x.x == y.x ? x.y < y.y : x.x < y.x);
}
int lb(int x) {
return x & -x;
}
void add(int x, int k) {
for (int i = x; i <= 2 * m; i += lb(i)) {
T[i] += k;
}
}
int ask(int x) {
int ans = 0;
for (int i = min(2 * m, x); i; i -= lb(i)) {
ans += T[i];
}
return ans;
}
void work() {
For(i,1,n) cin >> a[i].x >> a[i].y;
For(i,1,n) {
int x = (a[i].x - a[i].y), y = (a[i].x + a[i].y);
a[i].x = x, a[i].y = y;
}
sort(a + 1, a + n + 1, cmp);
For(i,1,n) {
while(t - h + 1 > 0 && a[i].x - a[q[h]].x > d) {
add(a[q[h]].y, -1);
h++;
}
Ans += (ask(a[i].y + d) - ask(max(0ll, a[i].y - d - 1)));
add(a[i].y, 1);
q[++t] = i;
}
cout << Ans << '\n';
}
}
#
发现
与
考虑如何转:
是将原坐标
时间复杂度
点击查看代码
namespace Solve3 {
const int L = 76;
struct Node {
int x, y, z, l;
} a[N];
int q[N], h = 1, t = 0, Ans = 0;
Int T[226][305][305] = {0};
bool cmp(Node x, Node y) {
return (x.x == y.x ? x.y < y.y : x.x < y.x);
}
int lb(int x) {
return x & -x;
}
void add(int x, int y, int z, int X) {
for (int i = x; i <= 3 * m; i += lb(i)) {
for (int j = y; j <= 3 * m + L; j += lb(j)) {
for (int k = z; k <= 3 * m + L; k += lb(k)) {
T[i][j][k] += X;
}
}
}
}
int ask(int x, int y, int z) {
int ans = 0;
for (int i = min(3 * m, x); i; i -= lb(i)) {
for (int j = min(3 * m + L, y); j; j -= lb(j)) {
for (int k = min(3 * m + L, z); k; k -= lb(k)) {
ans += T[i][j][k];
}
}
}
return ans;
}
void work() {
For(i,1,n) cin >> a[i].x >> a[i].y >> a[i].z;
For(i,1,n) {
int x = (a[i].x - a[i].y - a[i].z), y = (a[i].x + a[i].y + a[i].z),
z = (a[i].x + a[i].y - a[i].z) + L, l = (a[i].x - a[i].y + a[i].z) + L;
a[i].x = x, a[i].y = y, a[i].z = z, a[i].l = l;
}
sort(a + 1, a + n + 1, cmp);
For(i,1,n) {
while(t - h + 1 > 0 && a[i].x - a[q[h]].x > d) {
add(a[q[h]].y, a[q[h]].z, a[q[h]].l, -1);
h++;
}
int x1 = a[i].y + d, y1 = a[i].z + d, z1 = a[i].l + d;
int x2 = max(0ll, a[i].y - d - 1), y2 = max(0ll, a[i].z - d - 1), z2 = max(0ll, a[i].l - d - 1);
Ans += (ask(x1, y1, z1) - ask(x2, y1, z1) - ask(x1, y2, z1) - ask(x1, y1, z2)
+ ask(x2, y1, z2) + ask(x1, y2, z2) + ask(x2, y2, z1) - ask(x2, y2, z2));
add(a[i].y, a[i].z, a[i].l, 1);
q[++t] = i;
}
cout << Ans << '\n';
}
}
Code#
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define Int int
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int N = 1e5 + 10;
int B, n, d, m;
namespace Solve1 {
int a[N], q[N], h = 1, t = 0, ans = 0;
void work() {
For(i,1,n) cin >> a[i];
sort(a + 1, a + n + 1);
For(i,1,n) {
while(t - h + 1 > 0 && a[i] - a[q[h]] > d) h++;
ans += (t - h + 1);
q[++t] = i;
}
cout << ans << '\n';
}
}
namespace Solve2 {
struct Node {
int x, y;
} a[N];
int q[N], h = 1, t = 0, Ans = 0;
Int T[N * 2] = {0};
bool cmp(Node x, Node y) {
return (x.x == y.x ? x.y < y.y : x.x < y.x);
}
int lb(int x) {
return x & -x;
}
void add(int x, int k) {
for (int i = x; i <= 2 * m; i += lb(i)) {
T[i] += k;
}
}
int ask(int x) {
int ans = 0;
for (int i = min(2 * m, x); i; i -= lb(i)) {
ans += T[i];
}
return ans;
}
void work() {
For(i,1,n) cin >> a[i].x >> a[i].y;
For(i,1,n) {
int x = (a[i].x - a[i].y), y = (a[i].x + a[i].y);
a[i].x = x, a[i].y = y;
}
sort(a + 1, a + n + 1, cmp);
For(i,1,n) {
while(t - h + 1 > 0 && a[i].x - a[q[h]].x > d) {
add(a[q[h]].y, -1);
h++;
}
Ans += (ask(a[i].y + d) - ask(max(0ll, a[i].y - d - 1)));
add(a[i].y, 1);
q[++t] = i;
}
cout << Ans << '\n';
}
}
namespace Solve3 {
const int L = 76;
struct Node {
int x, y, z, l;
} a[N];
int q[N], h = 1, t = 0, Ans = 0;
Int T[226][305][305] = {0};
bool cmp(Node x, Node y) {
return (x.x == y.x ? x.y < y.y : x.x < y.x);
}
int lb(int x) {
return x & -x;
}
void add(int x, int y, int z, int X) {
for (int i = x; i <= 3 * m; i += lb(i)) {
for (int j = y; j <= 3 * m + L; j += lb(j)) {
for (int k = z; k <= 3 * m + L; k += lb(k)) {
T[i][j][k] += X;
}
}
}
}
int ask(int x, int y, int z) {
int ans = 0;
for (int i = min(3 * m, x); i; i -= lb(i)) {
for (int j = min(3 * m + L, y); j; j -= lb(j)) {
for (int k = min(3 * m + L, z); k; k -= lb(k)) {
ans += T[i][j][k];
}
}
}
return ans;
}
void work() {
For(i,1,n) cin >> a[i].x >> a[i].y >> a[i].z;
For(i,1,n) {
int x = (a[i].x - a[i].y - a[i].z), y = (a[i].x + a[i].y + a[i].z),
z = (a[i].x + a[i].y - a[i].z) + L, l = (a[i].x - a[i].y + a[i].z) + L;
a[i].x = x, a[i].y = y, a[i].z = z, a[i].l = l;
}
sort(a + 1, a + n + 1, cmp);
For(i,1,n) {
while(t - h + 1 > 0 && a[i].x - a[q[h]].x > d) {
add(a[q[h]].y, a[q[h]].z, a[q[h]].l, -1);
h++;
}
int x1 = a[i].y + d, y1 = a[i].z + d, z1 = a[i].l + d;
int x2 = max(0ll, a[i].y - d - 1), y2 = max(0ll, a[i].z - d - 1), z2 = max(0ll, a[i].l - d - 1);
Ans += (ask(x1, y1, z1) - ask(x2, y1, z1) - ask(x1, y2, z1) - ask(x1, y1, z2)
+ ask(x2, y1, z2) + ask(x1, y2, z2) + ask(x2, y2, z1) - ask(x2, y2, z2));
add(a[i].y, a[i].z, a[i].l, 1);
q[++t] = i;
}
cout << Ans << '\n';
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> B >> n >> d >> m;
if(B == 1) {
Solve1::work();
} else if(B == 2) {
Solve2::work();
} else {
Solve3::work();
}
return 0;
}
作者:Daniel-yao
出处:https://www.cnblogs.com/Daniel-yao/p/18313238
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】