1 /*
2 题意:BZOJ2957 n,m<=100000 在一个长度为n的直线上,每天在xi位置放置一个高度为yi的竖线,问每天在原点能够看到几个
3 题解:线段树解法,对于每个区间维护一个递增的序列,记录最大值,和最长的增长的长度
4 查询操作: 查询l,r区间大于M的有单调递增的有几个,如果左区间的最大值>=M,那么答案在右区间,否则,我们答案受到左区间的影响,可以用总长度-左区间的长度+左区间的询问长度
5 更新操作: 维护区间的最大值,
6 区间的最长的长度的更新: 左区间的长度+ 右区间大于左区间最大值的长度
7 时间:2018.07.19
8 */
9
10 #include <bits/stdc++.h>
11 using namespace std;
12
13 typedef long long LL;
14 const int MAXN = 100005;
15 const LL MOD7 = 1e9+7;
16
17
18 struct TreeNode
19 {
20 int l,r;
21 int ans;
22 double maxv;
23 }f[4*MAXN];
24
25 void build(int t,int l,int r)
26 {
27 f[t].l=l;f[t].r=r;
28 f[t].ans=0;f[t].maxv=0;
29 if (l==r) return;
30 int mid=(l+r)/2;
31 build(2*t,l,mid);
32 build(2*t+1,mid+1,r);
33 }
34
35 int query(int t,int l,int r,double M)
36 {
37 // printf("query %d %d %d %lf\n",t, l, r, M);
38 if (l==r) return f[t].maxv>M;
39 int mid=(f[t].l+f[t].r)/2;
40 if (f[2*t].maxv<=M) return query(2*t+1,mid+1,r,M);
41 return f[t].ans-f[2*t].ans+query(2*t,l,mid,M);
42 }
43
44 void update(int t,int k,double M)
45 {
46 if (f[t].l==k && f[t].r==k)
47 {
48 f[t].ans=1;
49 f[t].maxv=M;
50 return;
51 }
52 int mid=(f[t].l+f[t].r)/2;
53 if (k<=mid) update(2*t,k,M);
54 else update(2*t+1,k,M);
55 f[t].maxv = max(f[2*t].maxv,f[2*t+1].maxv);
56 f[t].ans=f[2*t].ans+query(2*t+1,mid+1,f[t].r,f[2*t].maxv);
57 }
58
59 int n,m;
60
61 int main()
62 {
63 #ifndef ONLINE_JUDGE
64 freopen("test.txt","r",stdin);
65 #endif // ONLINE_JUDGE
66 scanf("%d%d",&n,&m);
67 build(1, 1, n);
68 int x,y;
69 for (int i=1;i<=m;++i)
70 {
71 scanf("%d%d",&x,&y);
72 update(1,x,1.0*y/x);
73 // printf("%d\n",query(1,0,n,0));
74 printf("%d\n",f[1].ans);
75 }
76 return 0;
77 }