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\n",t[1].s); 60 } 61 return 0; 62 }