• 题解报告——窗口的星星


    题目背景

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

    题目描述

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

    输入输出格式

    输入格式:

    本题有多组数据,第一行为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
    ",res);
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    关于异常“The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine”的处理
    sqlserver怎么将查询出来的数据存到新的数据库表中
    如何使excel表格的内容自动添加前缀
    数据库中实现“替换功能”
    win7下安装sdks
    win7如何安装mircosoft SDKs
    如何从mysql中将数据导入到sqlserver
    Sql Server 查询多行并一行
    04-队列 Queue
    03-栈 Stack
  • 原文地址:https://www.cnblogs.com/genius777/p/8645181.html
Copyright © 2020-2023  润新知