bzoj2957 楼房重建

题目链接

如果一栋楼房可见,那么它一定满足它的最高点到(0,0)的连线不与其他楼房相交。

修改一个数只会对这个数后面的数造成影响。

所以,需要修改、查询区间[1,n]比之前的任何一个数都大的数有多少个?

转化一下就可以用线段树来维护了。

修改的时候就分情况递归处理左侧即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<string>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<ctime>
 9 #include<queue>
10 #include<stack>
11 #include<map>
12 #include<set>
13 using namespace std;
14 int n,m,q,w;
15 struct tree
16 {
17     double k;
18     int s;    
19 }t[400040];
20 int js(int x,int l,int r,double k)
21 {
22     if(l==r)return t[x].k>k;
23     int mid=(l+r)>>1,p1=x<<1,p2=x<<1|1;
24     if(t[p1].k<=k)return js(p2,mid+1,r,k);
25     return t[x].s-t[p1].s+js(p1,l,mid,k);
26 }
27 void change(int x,int l,int r,int p,double k)
28 {
29     if(l==r)
30     {
31         t[x].k=k,t[x].s=1;
32         return ;
33     }
34     int mid=(l+r)>>1,p1=x<<1,p2=x<<1|1;
35     if(p<=mid)change(p1,l,mid,p,k);
36     else change(p2,mid+1,r,p,k);
37     t[x].k=max(t[p1].k,t[p2].k);
38     t[x].s=t[p1].s+js(p2,mid+1,r,t[p1].k);
39 }
40 int getint()
41 {
42     int ret=0,f=1;
43     char ch=getchar();
44     while(ch<'0'||ch>'9')
45     {
46         if(ch=='-')f=-1;
47         ch=getchar();
48     }
49     while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar();
50     return f==1?ret:-ret;
51 }
52 int main()
53 {
54     n=getint(),m=getint();
55     for(int i=1;i<=m;i++)
56     {
57         scanf("%d%d",&q,&w);
58         change(1,1,n,q,(double)w/q);
59         printf("%d
",t[1].s);
60     }
61     return 0;
62 }
原文地址:https://www.cnblogs.com/HugeGun/p/5151126.html