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;
}
posted @ 2022-10-11 22:35  zyy2001  阅读(159)  评论(0编辑  收藏  举报