BZOJ2957: Building Reconstruction

【Portal: BZOJ2957


Brief title:

  Given a plane rectangular coordinate system, there is a person standing at (0,0), the value range of the x-axis is 1<=x<=n

  There are m operations, each operation inputs x, y, which means to build a building at (x, 0) with a height of y, if there is no building at (x, 0), it is regarded as a new building, otherwise it is regarded as a renovation

  For a building, it can be seen if and only if the line connecting its highest point with (0,0) has no intersection with other buildings

  Find the number of buildings this person can see after each operation


answer:

  good line segment tree

  For a building to be seen, it can be seen that the slope of its connection to (0,0) is greater than all previous slopes

  Then we can treat each operation as a single-point modification, and then find the number of buildings obtained by increasing the slope of the entire interval from the first building

  Let mx be the maximum slope in each interval, and c be the number of buildings that can be seen from the left endpoint of each interval

  Obviously we need to maintain the segment tree when modifying

  For an interval, it is obvious that the contribution of the c value of the left subinterval must be all in the c value of the entire interval, so we only need to process the right subinterval

  If the maximum value of the current left subinterval >= the maximum value of the right subinterval, then the right subinterval does not contribute to the entire interval

  Otherwise, find the first building in the right sub-interval that is greater than the maximum value of the left sub-interval, and then contribute to the number of buildings (including this building) obtained from this building afterward.

  That's it, just pay attention to the accuracy


Reference Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define eps 1e-10
using namespace std;
struct trnode
{
    int l,r,lc,rc,c;
    double mx;
}tr[210000];int trlen;
void bt(int l,int r)
{
    int now=++trlen;
    tr[now].l=l;tr[now].r=r;
    tr[now].lc=tr[now].rc=-1;
    tr[now].c=0;tr[now].mx=0.0;
    if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
int ans;
void findd(int now,double d)
{
    if(tr[now].l==tr[now].r){ans++;return ;}
    int lc=tr[now].lc,rc=tr[now].rc;
    if(tr[lc].mx<=d) findd(rc,d);
    else ans+=tr[now].c-tr[lc].c,findd(lc,d);
}
void follow(int now)
{
    int lc=tr[now].lc,rc=tr[now].rc;
    tr[now].c=tr[lc].c;tr[now].mx=tr[lc].mx;
    if(tr[rc].mx-tr[lc].mx>eps)
    {
        tr[now].mx=tr[rc].mx;
        ans = 0 ; findd(rc,tr[lc].mx);
        tr[now].c+=ans;
    }
}
void change(int now,int x,double d)
{
    if(tr[now].l==tr[now].r)
    {
        tr[now].mx=d;
        tr[now].c=1;
        return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(x<=mid) change(lc,x,d);
    else change(rc,x,d);
    follow(now);
}
intmain ()
{
    int n,m;
    scanf("%d%d",&n,&m);
    trlen=0;bt(1,n);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        change(1,x,double(y)/double(x));
        printf("%d\n",tr[1].c);
    }
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324612880&siteId=291194637