【原题题面】传送门
【题面大意】
给出每颗星星的坐标和亮度,在h,w的矩形范围内,内圈住的星星的最大亮度和。(边界上的星星不算)
【题解大意】
如何转化成扫描线问题?
将每个星星能够产生贡献的范围设为矩形
星星位于产生贡献的矩形的某个固定位置
这样产生贡献的计算才不重不漏。
具体操作:
同样将每颗星星的用结构体(四元体)记录。
每颗星星照例要用两个四元组储存,分别记录正贡献和负贡献
线段树记录纵坐标的c值。
查询任意区间长度为H,[i,i+H-1]中的和的最大值得出答案。
【code】
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define File "stars" #define ll long long inline void file(){ freopen(File".in","r",stdin); freopen(File".out","w",stdout); } inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();} return x*f; } const int mxn = 1e4+5; int n,W,H; struct T{ int l,r,dat,tg; }tr[mxn<<3]; struct P{ int x,y1,y2,c; bool operator <(const P t) const { return x == t.x ? c < t.c : x < t.x; } }p[mxn<<1]; int a[mxn<<1]; #define ls p<<1 #define rs p<<1|1 inline void B(int p,int l,int r){ tr[p].l = l,tr[p].r = r; tr[p].dat = tr[p].tg = 0; if(l == r) return; int mid = l+r >>1; B(ls,l,mid),B(rs,mid+1,r);//!!! } inline void push(int p){ int tg = tr[p].tg; if(tg){ tr[ls].tg += tg; tr[rs].tg += tg; tr[ls].dat += tg; tr[rs].dat += tg; tr[p].tg = 0; } } inline void U(int p,int l,int r,int c){ if(l <= tr[p].l && tr[p].r <= r){ tr[p].dat += c; tr[p].tg += c; return; } push(p); int mid = tr[p].l+tr[p].r >>1; if(l <= mid) U(ls,l,r,c); if(r > mid) U(rs,l,r,c); tr[p].dat = max(tr[ls].dat,tr[rs].dat); } int main(){ // file(); while(~scanf("%d%d%d",&n,&W,&H)){ // n = read(),W = read(),H = read(); for(int i = 1;i <= n; ++i){ int x,y,c; x = read(),y = read(),c = read(); // double x,y; int c; // scanf("%lf %lf %d",&x,&y,&c); int id = i<<1; a[id-1] = y,a[id] = y+H-1; //储存y值 p[id-1].x = x,p[id].x = x+W; p[id-1].y1 = p[id].y1 = y; p[id-1].y2 = p[id].y2 = y+H-1; p[id-1].c = c,p[id].c = -c; } n <<= 1; sort(a+1,a+n+1);//按y值排序,离散化 int m = unique(a+1,a+n+1)-(a+1); for(int i = 1;i <= n; ++i){ p[i].y1 = lower_bound(a+1,a+m+1,p[i].y1)-a; p[i].y2 = lower_bound(a+1,a+m+1,p[i].y2)-a; } sort(p+1,p+n+1); B(1,1,m); int ans = 0; for(int i = 1;i <= n; ++i){ int y1 = p[i].y1,y2 = p[i].y2,c = p[i].c; U(1,y1,y2,c); ans = max(ans,tr[1].dat); } cout << ans << endl; } return 0; } /* 3 5 4 1 2 3 2 3 2 6 3 1 3 5 4 1 2 3 2 3 2 5 3 1 */ /* 小数据点过了但大数据点没过 可能是: 1.没开ll或double爆精度 2.算法本身有bug 3.tle变成了wa 4.mle变成了wa 5.数组边界和更新 6.变量的初值和变化 */