bzoj 2957 楼房重建 (线段树+思路)
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2957
思路:
用分块可以很简单的过掉,但是这道题也可以用线段树写。
分类讨论左区间最大值对右区间取值的影响,这样每次都只计算左右区间其中一个,复杂度就降成了logn.
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 1e5 + 10; double mx[M<<2]; int sum[M<<2]; int query(double c,int l,int r,int rt){ mid; if(l == r) return mx[rt] > c; if(mx[rt] <= c) return 0; if(mx[rt<<1] <= c) return query(c,rson); else return sum[rt] - sum[rt<<1] + query(c,lson); } void update(int p,double c,int l,int r,int rt){ if(l == r){ sum[rt] = 1; mx[rt] = c; return ; } mid; if(p <= m) update(p,c,lson); else update(p,c,rson); mx[rt] = max(mx[rt<<1],mx[rt<<1|1]); sum[rt] = sum[rt<<1] + query(mx[rt<<1],rson); } int main() { int n,m,x,y; scanf("%d%d",&n,&m); while(m--){ scanf("%d%d",&x,&y); double c = (double)y/x; update(x,c,1,n,1); printf("%d\n",sum[1]); } }