2847. 老C的任务
题目链接
2847. 老C的任务
老 \(C\) 是个程序员。
最近老 \(C\) 从老板那里接到了一个任务——给城市中的手机基站写个管理系统。
作为经验丰富的程序员,老 \(C\) 轻松地完成了系统的大部分功能,并把其中一个功能交给你来实现。
由于一个基站的面积相对于整个城市面积来说非常的小,因此每个的基站都可以看作坐标系中的一个点,其位置可以用坐标 \((x,y)\) 来表示。
此外,每个基站还有很多属性,例如高度、功率等。
运营商经常会划定一个区域,并查询区域中所有基站的信息。
现在你需要实现的功能就是,对于一个给定的矩形区域,回答该区域中(包括区域边界上的)所有基站的功率总和。
如果区域中没有任何基站,则回答 \(0\)。
输入格式
第一行两个整数 \(n, m\),表示一共有 \(n\) 个基站和 \(m\) 次查询。
接下来一共有 \(n\) 行,每行由 \(x_i , y_i , p_i\) 三个空格隔开的整数构成,表示一个基站的坐标 \((x_i, y_i)\) 和功率 \(p_i\)。不会有两个基站位于同一坐标。
接下来一共有 \(m\) 行,每行由 \(x_{1j},y_{1j},x_{2j},y_{2j}\) 四个空格隔开的整数构成,表示一次查询的矩形区域。该矩形对角坐标为 \((x_{1j} , y_{1j})\) 和 \((x_{2j} , y_{2j})\),且 \(4\) 边与坐标轴平行。
输出格式
输出 \(m\) 行,每行一个整数,对应每次查询的结果。
数据范围
\(1 \le n,m \le 10^5\),
\(-2^{31} ≤ x_i,y_i,p_i,x_{1j},y_{1j},x_{2j},y_{2j} < 2^{31}\),
\(x_{1j} ≤ x_{2j}, y_{1j} ≤ y_{2j}\)。
输入样例1:
4 2
0 0 1
0 1 2
2 2 4
1 0 8
0 0 1 1
1 1 5 6
输出样例1:
11
4
输入样例2:
3 2
-100 0 16
1 -10 32
1000 100 64
0 0 0 1
-1000 -1000 10000 10000
输出样例2:
0
112
解题思路
cdq分治
增加一个维度 \(z\),\(z=0\) 表示计算点,\(z=1\) 表示询问点,然后利用二维前缀和计算答案,对于查询的矩形,其四个点都为查询点,然后利用 \(cdq分治\) 即可解决此题,另外由于 \(z\) 只有两个值:\(0\) 或 \(1\),故可以不用树状数组维护第三维的信息,直接用个变量统计 \(z=0\) 的信息即可,另外也不需要判重,对于出现相等的点,\(id\) 自然会区分且不影响答案
- 时间复杂度:\(O(nlogn)\)
代码
// Problem: 老C的任务
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2849/
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=5e5+5;
int n,m;
LL res[N];
struct A
{
int x,y,z,sign,id;
LL p;
bool operator<(const A &o)const
{
if(x!=o.x)return x<o.x;
if(y!=o.y)return y<o.y;
return z<o.z;
}
}a[N],b[N];
void merge_sort(int l,int r)
{
if(l>=r)return ;
int mid=l+r>>1;
merge_sort(l,mid),merge_sort(mid+1,r);
int i=l,j=mid+1,k=0;
LL res=0;
while(i<=mid&&j<=r)
if(a[i].y<=a[j].y)res+=!a[i].z*a[i].p,b[++k]=a[i++];
else
a[j].p+=a[j].z*res,b[++k]=a[j++];
while(i<=mid)res+=!a[i].z*a[i].p,b[++k]=a[i++];
while(j<=r)a[j].p+=a[j].z*res,b[++k]=a[j++];
for(int i=l,j=1;j<=k;j++,i++)a[i]=b[j];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y>>a[i].p;
int k=n;
for(int i=1;i<=m;i++)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
a[++k]={x2,y2,1,1,i};
a[++k]={x1-1,y1-1,1,1,i};
a[++k]={x2,y1-1,1,-1,i};
a[++k]={x1-1,y2,1,-1,i};
}
sort(a+1,a+1+k);
merge_sort(1,k);
for(int i=1;i<=k;i++)res[a[i].id]+=a[i].z*a[i].p*a[i].sign;
for(int i=1;i<=m;i++)cout<<res[i]<<'\n';
return 0;
}