题目
在第一象限,每颗星星都有亮度,用一个固定长宽的矩形套住星星,使星星的总亮度最大,并且星星不能在矩形的边界上
分析
这道题可以发现如果矩形的左下角是(x,y)(x,y)(x,y),那么右上角就是(x+r,y+c)(x+r,y+c)(x+r,y+c),那么其实可以用扫描线维护横坐标,纵坐标通过线段树得出,然而我比较懒,所以就用zkw线段树,标记永久化
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef unsigned uit;
struct rec{uit x,y1,y2; int w;}a[20001];
uit n,r,c,ty[20001]; int w[50001];
uit in(){
uit ans=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(uit ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
bool cmp(const rec &a,const rec &b){if (a.x!=b.x) return a.x<b.x; else return a.w<b.w;}
int max(int a,int b){return (a>b)?a:b;}
void change(uit k){
int t=max(w[k<<1],w[k<<1|1]);
w[k]+=t; w[k<<1]-=t; w[k<<1|1]-=t;
}
int main(){
while (1){
if (scanf("%d",&n)!=1) break; r=in(); c=in();
memset(w,0,sizeof(w));
for (register uit i=1;i<=n;i++){
uit x=in(); uit y=in(); int w=in();
a[i-1<<1|1].x=x; a[i-1<<1|1].y1=y; a[i-1<<1|1].y2=y+c; a[i-1<<1|1].w=w; ty[i-1<<1|1]=y;
a[i<<1].x=x+r; a[i<<1].y1=y; a[i<<1].y2=y+c; a[i<<1].w=-w; ty[i<<1]=y+c;
}
std::stable_sort(ty+1,ty+1+(n<<1));
std::stable_sort(a+1,a+1+(n<<1),cmp);
uit m=std::unique(ty+1,ty+1+(n<<1))-(ty+1);
uit ans=0; uit end=1; while ((end<<=1)<m+2);
for (register uit i=1;i<=n<<1;i++){
uit x=std::lower_bound(ty+1,ty+1+m,a[i].y1)-ty;//离散后二分
uit y=std::lower_bound(ty+1,ty+1+m,a[i].y2)-ty-1;
for (x+=end-1,y+=end+1;x^y^1;x>>=1,y>>=1){//瞬间跳到叶子节点
if (!(x&1)) w[x+1]+=a[i].w;//从闭区间到开区间
if (y&1) w[y-1]+=a[i].w;
change(x>>1); change(y>>1);
}
for (x>>=1;x;x>>=1) change(x);
ans=max(ans,w[1]);
}
print(ans); putchar('\n');
}
return 0;
}