[Luogu P4198] Building reconstruction (line segment tree)

Topic 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, it can be smaller than the original - demolish, or even keep the same - what is the construction team doing today? neither did). Please help Xiao A to count how many buildings he can see every day after the construction team finishes?

Input and output format

Input format:

The first line contains two positive integers N,M

Next M lines, each line contains two positive integers Xi, Yi

Output format:

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

Input and output example

Input Example #1: Copy
3 4
2 4
3 6
1 1000000000
1 1
Output Sample #1: Copy
1
1
1
2

illustrate

For all data 1<=Xi<=N, 1<=Yi<=10^9

N,M<=100000

The line segment tree is broad and profound.

y/x is used as the value of each point to find the leftmost extremely long ascending subsequence, and the line segment tree is maintained.

Consider how to merge two intervals, let c[x] be the length of the subsequence in the x interval. Obviously, the extremely long ascending subsequence on the left is selected, and then the extremely long ascending subsequence whose first number is greater than max{all numbers on the left (that is, the end of the left subsequence)} is selected on the right.

As for how to find the length of the subsequence whose first number is greater than a certain value in an interval, and then use a function to solve it, que(x,k) represents the length of the extremely long ascending subsequence greater than k in the interval of the x node, recursive query That's it.

When implemented, it will be found that it is the mutual use of c[] and find(), which is more ingenious.

Because the modification will bring the query, so the complexity $O(n\log^2 n)$

In addition, the data type of this question is a real number. You will find that there is no problem if you do not consider the precision problem at all when comparing real numbers (using operations such as >= directly), and if you consider it, if the eps is set wider, you will not get points. eps is set to 1e-10 to get points.

It seems to have seen the fiasco of NOIP2017D2T1 again.

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define ls (x<<1)
 5 #define rs (ls|1)
 6 #define lson ls,L,mid
 7 #define rson rs,mid+1,R
 8 #define rep(i,l,r) for (int i=l; i<=r; i++)
 9 typedef long long ll;
10 using namespace std;
11 
12 const int N=100100;
13 const double eps=1e-10;
14 int n,m,x,c[N<<2];
15 double y,mx[N<<2];
16 
17 int que(int x,int L,int R,double k){
18     if (k-mx[x]>-eps) return 0;
19     if (L==R) return c[x];
20     int mid=(L+R)>>1;
21     if (k-mx[ls]>-eps) return que(rson,k);
22         else return que(lson,k)+c[x]-c[ls];
23 }
24 
25 void mdf(int x,int L,int R,int pos,double k){
26     if (L==R){ mx[x]=k; if (fabs(k)<eps) c[x]=0; else c[x]=1; return; }
27     int mid=(L+R)>>1;
28     if (pos<=mid) mdf(lson,pos,k); else mdf(rson,pos,k);
29     mx[x]=max(mx[ls],mx[rs]);
30     if (c[ls]==0) c[x]=c[rs]; else c[x]=c[ls]+que(rson,mx[ls]);
31 }
32 
33 int main(){
34     freopen("P4198.in","r",stdin);
35     freopen("P4198.out","w",stdout);
36     scanf("%d%d",&n,&m);
37     rep(i,1,m)
38     scanf("%d%lf",&x,&y),mdf( 1,1,n,x,y/x),printf("%d\n",c[1]);
39     return 0;
40 }

 

Guess you like

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