题解报告——窗口的星星

题目背景

小卡买到了一套新房子,他十分的高兴,在房间里转来转去。

题目描述

晚上,小卡从阳台望出去,“哇~~~~好多星星啊”,但他还没给其他房间设一个窗户,天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。这时小卡使用了超能力(透视术)知道了墙后面每个星星的位置和亮度,但是小卡发动超能力后就很疲劳,只好拜托你告诉他最多能够有总和多亮的星星能出现在窗口上。

输入输出格式

输入格式:

 

本题有多组数据,第一行为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个整数,表示每组数据中窗口星星亮度总和的最大值。

 

输入输出样例

输入样例#1:
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
输出样例#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\n",res);
117     }
118     return 0;
119 }

 

posted @ 2018-03-25 16:12  genius777  阅读(443)  评论(0编辑  收藏  举报