解法:扫描线
炸弹的范围是R,可以看成每个城市的影响范围是R,找出最多的重叠部分就可以了
时间复杂度$O(NlogM)$ N是城市个数,M是坐标范围
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxn = 1e5 + 233;
#define ls(x) (x << 1)
#define rs(x) ((x << 1) + 1)
struct Node{
int l, r, dat, mk;
#define l(x) t[x].l
#define r(x) t[x].r
#define dat(x) t[x].dat
#define mk(x) t[x].mk
}t[maxn * 4];
void build(int p, int l, int r)
{
l(p) = l; r(p) = r;
if(l == r)
{
dat(p) = 0; mk(p) = 0;
return ;
}
int mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
dat(p) = 0; mk(p) = 0;
}
void spr(int p)
{
if(mk(p))
{
dat(ls(p)) += mk(p);
dat(rs(p)) += mk(p);
mk(ls(p)) += mk(p);
mk(rs(p)) += mk(p);
mk(p) = 0;
}
}
void update(int p, int l, int r, int v)
{
if(l <= l(p) && r >= r(p))
{
dat(p) += v;
mk(p) += v;
return ;
}
spr(p);
int mid = (l(p) + r(p)) >> 1;
if(l <= mid) update(ls(p), l, r, v);
if(r > mid) update(rs(p), l, r, v);
dat(p) = max(dat(ls(p)), dat(rs(p)));
}
int ask(int p, int l, int r)
{
if(l <= l(p) && r >= r(p)) return dat(p);
spr(p);
int mid = (l(p) + r(p)) >> 1;
int res = 0;
if(l <= mid) res = max(res, ask(ls(p), l, r));
if(r > mid) res = max(res, ask(rs(p), l, r));
return res;
}
vector<pair<int, pair<int,pii> > > org;
int main()
{
int n, r;
cin >> n >> r;
for(int i = 1; i <= n; i++)
{
int x, y, z;
cin >> x >> y >> z;
y++;
org.push_back({x,{z, {y, y + r - 1}}});
org.push_back({x + r,{-z, {y, y + r - 1}}});
}
sort(org.begin(), org.end());
int ans = 0;
build(1,1,20001);
for(int i = 0; i < org.size(); i++)
{
pii now = org[i].second.second;
int ty = org[i].second.first;
update(1, now.first, now.second, ty);
ans = max(ans, ask(1, 1, 20001));
}
cout<<ans;
}
大佬,你的代码有问题啊,可能是更新样例了,样例通不过,我想的是在线段树去更新一段正方形区域前,需要提前把负数全去掉,否则会多计算之前已经无效的区域。
牛逼,并查集都忘得差不多了
有一点不太理解 请教下。
重叠面积是城市个数最多 但是不是价值最大吧?
对应把扫面线加上权值就行了
了解 谢谢