题目背景
小卡买到了一套新房子,他十分的高兴,在房间里转来转去。
题目描述
晚上,小卡从阳台望出去,“哇~~~~好多星星啊”,但他还没给其他房间设一个窗户,天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。这时小卡使用了超能力(透视术)知道了墙后面每个星星的位置和亮度,但是小卡发动超能力后就很疲劳,只好拜托你告诉他最多能够有总和多亮的星星能出现在窗口上。
输入输出格式
输入格式:
本题有多组数据,第一行为T 表示有T组数据T<=10
对于每组数据
第一行3个整数n,W,H,(n<=10000,1<=W,H<=1000000)表示有n颗星星,窗口宽为W,高为H。
接下来n行,每行三个整数xi,yi,li 表示星星的坐标在(xi,yi),亮度为li。(0<=xi,yi<2^31)
输出格式:
T个整数,表示每组数据中窗口星星亮度总和的最大值。
输入输出样例
2 3 5 4 1 2 3 2 3 2 6 3 1 3 5 4 1 2 3 2 3 2 5 3 1
5 6
说明
小卡买的窗户框是金属做的,所以在边框上的不算在内。
【思路分析】
看到这道题其实还是懵了一会儿,这是计算几何???,很明显不可做嘛,正打算跳题,旁边的大佬就提醒了一句,这不是计算几何,好嘛,那就再看看呗,突然发现,难道不可以用前不久刚学的扫描线来gank一波吗。
没错扫描线!!!可有人可能会问了,这道题全是点,哪来的线给你扫啊,很好,这就是这道题的关键了。
我们使用矩形去框这些星星们,但是我们为何不把星星转换成一个矩形呢,假设每个星星都可以几万W地放光,那些光不就可以看作一个区域了吗?!!
我们假设以星星所在点的位置看作发光区域的左下角,发光区看作一个和窗户一样高,宽的矩形,那我们只需要统计最多一个地方有多少个矩形重叠就行了。。。
是不是一下就舒服了很多,回归到了我们美妙的扫描线了!!!
【注意事项】
这道题叙述的边框不能看到星星,这是一个很坑的,要多加注意判断,个人认为,题目都很恶心了,还要一个这么扯淡的条件,很烦的!!!
还有就是多组数据!!!必须要在每次建线段树的时候注意清空,答案也要赋初值,不然就要和我一样,一直爆10分,也不知道为什么。。。
【代码实现】
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 struct edge{ 7 int h,lx,rx,s; 8 }line[20005]; 9 struct sd{ 10 int son[2],l,r,len,s; 11 }t[40005]; 12 int X[20005]; 13 int cnt; 14 bool cmp(edge a,edge b) 15 { 16 if(a.h==b.h) return a.s>b.s; 17 return a.h<b.h; 18 } 19 void build(int &v,int l1,int r1) 20 { 21 cnt++;v=cnt; 22 t[v].l=l1,t[v].r=r1,t[v].len=0,t[v].s=0; 23 if(l1==r1) return; 24 int mid=(l1+r1)>>1; 25 build(t[v].son[0],l1,mid); 26 build(t[v].son[1],mid+1,r1); 27 } 28 int find(int l1,int r1,int key) 29 { 30 while(l1<=r1) 31 { 32 int mid=(l1+r1)/2; 33 if(X[mid]==key) return mid; 34 else 35 if(X[mid]<key) l1=mid+1; 36 else r1=mid-1; 37 } 38 } 39 void pushup(int v) 40 { 41 t[v].len=max(t[t[v].son[0]].len,t[t[v].son[1]].len); 42 } 43 void pushdown(int v) 44 { 45 if(t[v].s==0) return; 46 if(t[v].l!=t[v].r) 47 { 48 int ls=t[v].son[0],rs=t[v].son[1]; 49 t[ls].s+=t[v].s; 50 t[ls].len+=t[v].s; 51 t[rs].s+=t[v].s; 52 t[rs].len+=t[v].s; 53 } 54 t[v].s=0; 55 } 56 void update(int v,int l1,int r1,int c) 57 { 58 pushdown(v); 59 if(t[v].l==l1&&t[v].r==r1) 60 { 61 t[v].len+=c; 62 t[v].s+=c; 63 pushdown(v); 64 return; 65 } 66 int mid=(t[v].l+t[v].r)>>1; 67 if(r1<=mid) update(t[v].son[0],l1,r1,c); 68 else 69 if(l1>mid) update(t[v].son[1],l1,r1,c); 70 else 71 { 72 update(t[v].son[0],l1,mid,c); 73 update(t[v].son[1],mid+1,r1,c); 74 } 75 pushup(v); 76 } 77 int main() 78 { 79 int T; 80 scanf("%d",&T); 81 while(T--) 82 { 83 cnt=0; 84 int n,W,H; 85 scanf("%d%d%d",&n,&W,&H); 86 for(int i=1;i<=n;i++) 87 { 88 int x1,y1,val; 89 scanf("%d%d%d",&x1,&y1,&val); 90 line[i].lx=x1,line[i].rx=x1+W-1,line[i].h=y1,line[i].s=val; 91 X[i]=x1; 92 line[i+n].lx=x1,line[i+n].rx=x1+W-1,line[i+n].h=y1+H-1,line[i+n].s=-val; 93 X[i+n]=x1+W-1; 94 } 95 sort(X+1,X+1+n*2); 96 sort(line+1,line+1+n*2,cmp); 97 int k=0;X[n*2+1]=-1; 98 for(int i=1;i<=n*2;i++) 99 { 100 if(X[i]!=X[i+1]) 101 { 102 k++;X[k]=X[i]; 103 } 104 } 105 int root=0; 106 build(root,1,k); 107 int res=0; 108 for(int i=1;i<=n*2;i++) 109 { 110 int ll=find(1,k,line[i].lx); 111 int rr=find(1,k,line[i].rx); 112 113 update(1,ll,rr,line[i].s); 114 res=max(res,t[1].len); 115 } 116 printf("%d ",res); 117 } 118 return 0; 119 }