BZOJ 2597 楼房重建 (分块/线段树)
题意
一个1e5的double数组,前面大的元素会挡住后面小的元素,有1e5个操作,每次改变一个元素的值,问你每次改完之后有多少元素没有被挡
思路
考虑分块,对每一个块维护一个单独的答案,那么总的答案一定是各块单独的答案的一部分合起来
每次修改之后只需要重新计算本块的答案,并且对每一块二分接上的位置,并统计答案
线段树做法待更
代码
分块做法
开始精度设置的1e-6,wa了
int n,t,m;
double a[maxn];
double mx[maxn];
int cnt[maxn];
int go(int x){
return (x+t-1)/t;
}
vector<double>v[maxn];
int main() {
scanf("%d %d", &n,&m);
t=sqrt(n);
int tot = (n+t-1)/t;
v[0].pb(0);
for(int i = 1; i <= m; i++){
int x,y;
scanf("%d %d", &x ,&y);
a[x]=1.0*y/x;
int now = go(x);
int l = (now-1)*t+1,r=min(n,now*t);
double lst = 0;
v[now].clear();
for(int j = l; j <= r; j++){
if(a[j]>lst+eps){
lst=a[j];v[now].pb(a[j]);
}
}
int ans = 0;
lst =0;
for(int j = 1; j <= tot; j++){
int x = lower_bound(v[j].begin(),v[j].end(),lst+eps)-v[j].begin()+1;
int tmp = v[j].size()-x+1;
if(tmp)lst=v[j].back();
ans+=tmp;
}
printf("%d\n",ans);
}
return 0;
}