BZOJ 2957

 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 }

 

posted @ 2018-07-19 11:17  LeeSongt  阅读(236)  评论(0编辑  收藏