【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; }