2957. Building Reconstruction【Line Segment Tree】

Description

  There is a large construction site outside Xiao A's building, and there are N buildings to be built on the site. Every day, houses on this site are demolished and built, built and demolished. He often stared out the window in a daze, counting how many houses he could see.
  To simplify the problem, we consider these events to occur on a two-dimensional plane. The position of small A on the plane at (0,0), the i-th building can be represented by a line segment connecting (i, 0) and (i, Hi), where Hi is the height of the i-th building. If any point on the building with a height greater than 0 and the line connecting (0,0) does not intersect the previous line segment, then the building is considered visible.
  The construction of the construction team took a total of M days. Initially, all buildings have not yet started construction, and their height is 0. On the ith day, the construction team will change the height of the house whose abscissa is Xi to Yi (the height can be larger than the original---build, or smaller than the original---demolition, or even keep the same--- The construction team did nothing that day). Please help Xiao A to count how many buildings he can see every day after the construction team finishes?

Input

  The first line contains two positive integers N, M and
  the next M lines, each line contains two positive integers Xi, Yi

Output

  Line M, an integer in line i indicates how many buildings Xiao A can see after the ith day

Sample Input

3 4
2 4
3 6
1 1000000000
1 1

Sample Output

1
1
1
2
Data convention
  For all data 1<=Xi<=N, 1<=Yi<=10^9
N,M<=100000

 
I did a morning of calculation and geometry, copied the wave board, was disgusted, and then my mind exploded.
Then I slumped all afternoon
 
A very good line segment tree question...
It is easy to consider that we can maintain the slope to count the answer.
Then , for an interval, we maintain two pieces of information, max and sum
, which represent the maximum slope in the interval, and if we only consider this interval, we can see that For several buildings
in an interval [l, r], if the maximum value of [l, mid] is greater than or equal to the maximum value of [mid+1, r], it is obvious that the contribution of the interval on the right is not considered (because it is all covered by the left Block 233)
So every time we merge the current interval information Segt[now], we calculate Segt[now].max directly, Segt[now].sum=sum of the left son+ Calculate

how to calculate the contribution that the right son can make Contribution, we can recursively process the interval of the right child. Let the maximum value of the left son be maxn, and the interval Segt[k] from the current recursive processing to the right son
1. If Segt[k].max≤maxn, the contribution is 0
2. If Segt[k*2].max≤maxn, Then Segt[k*2+1] must be greater than maxn, we will recursively process Segt[k*2+1]
3. If Segt[k*2].max>maxn, then we will calculate Segt[ Contributions of k*2] and Segt[k*2+1].
For Segt[k*2], the recursive processing continues. Then add the contribution of Segt[k*2+1]
(because it is not maxn that affects the right segment, but the maximum value of the left segment),
but the contribution of Segt[k*2+1] cannot be added directly, To add the contribution of the current segment - the contribution of the left segment.
Because the contribution of the current paragraph ≠ the contribution of the left paragraph + the right paragraph (Why did I suddenly sb when I wrote the question)
Complexity Nlog²N
 
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 struct node{double max;int sum;}Segt[400009];
 6 int n,m,x,k;
 7 
 8 int Calc(int now,double maxn,int l,int r)
 9 {
10     int mid=(l+r)>>1;
11     if (l==r) return Segt[now].max>maxn;
12     if (Segt[now].max<=maxn) return 0;
13     if (Segt[now<<1].max<=maxn) return Calc(now<<1|1,maxn,mid+1,r);
14     else return Segt[now].sum-Segt[now<<1].sum+Calc(now<<1,maxn,l,mid);
15 }
16 
17 void Update(int now,int l,int r,int x,double k)
18 {
19     if (l==r)
20     {
21         Segt[now].max=k;
22         Segt[now].sum=1;
23         return;
24     }
25     int mid=(l+r)>>1;
26     if (x<=mid) Update(now<<1,l,mid,x,k);
27     else Update(now<<1|1,mid+1,r,x,k);
28     Segt[now].max=max(Segt[now<<1].max,Segt[now<<1|1].max);
29     Segt[now].sum=Segt[now<<1].sum+Calc(now<<1|1,Segt[now<<1].max,mid+1,r);
30 }
31 
32 int main()
33 {
34     scanf("%d%d",&n,&m);
35     for (int i=1; i<=m; ++i)
36     {
37         scanf("%d%d",&x,&k);
38         Update(1,1,n,x,k*1.0/x);
39         printf("%d\n",Segt[1].sum);
40     }
41 }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326560457&siteId=291194637