G - 楼房重建 (线段树)
题目链接:https://cn.vjudge.net/contest/281960#problem/G
题目大意:中文问题
具体思路:首先每一个点的值可以用当前这个点的斜率来表示,每一次输入一个值,我们先看当前这个点之前的区域中有多少点是小于当前这个点的斜率的,这样每一次查询就可以了。
查询的时候:首先对于当前的点的左区间,肯定是包含关系,对于右区间的话,需要考虑到左区间会遮挡住右区间的情况。
我们就按照递归的形式,如果说当前的maxx[rt]<=val,我们就再去查询这个区间的右区间,看看这一段有没有符合的。
其次的话,我们就每一次判断左区间有多少符合的就可以了。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define lson l,m,rt<<1 5 # define rson m+1,r,rt<<1|1 6 const int maxn = 6e5+5; 7 int ans[maxn]; 8 double maxx[maxn]; 9 int cal(int l,int r,int rt,double val) 10 { 11 if(l==r) 12 return maxx[rt]>val; 13 int m=(l+r)>>1; 14 if(maxx[rt<<1]<=val) 15 return cal(rson,val); 16 return ans[rt]-ans[rt<<1]+cal(lson,val); 17 } 18 void up(int l,int r,int rt) 19 { 20 maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]); 21 int m=(l+r)>>1; 22 ans[rt]=ans[rt<<1]+cal(rson,maxx[rt<<1]); 23 } 24 void update(int l,int r,int rt,int pos,double val) 25 { 26 if(l==r) 27 { 28 ans[rt]=1; 29 maxx[rt]=val; 30 return ; 31 } 32 int m=(l+r)>>1; 33 if(pos<=m) 34 update(lson,pos,val); 35 if(pos>m) 36 update(rson,pos,val); 37 up(l,r,rt); 38 } 39 int main() 40 { 41 int n,m,t1,t2; 42 scanf("%d %d",&n,&m); 43 for(int i=1; i<=m; i++) 44 { 45 scanf("%d %d",&t1,&t2); 46 update(1,n,1,t1,(t2*1.0)/(t1*1.0)); 47 printf("%d\n",ans[1]); 48 } 49 return 0; 50 }