楼房重建 HYSBZ - 2957;
分块大法好啊>>分块大法妙啊>>太6了>>太暴力了
分块的思路:维护每一块的上升子序列>>该子序列中以斜率为值进行维护>>
每次更新楼房高度,需要暴力更新该块的上升子序列
每次查询答案:以上一块的最大斜率为起点值>>二分查找>>拼接起来
复杂度是sqrt(n)*log(sqrt(n))
所以总复杂度是>>m*sqrt(n)log(sqrt(n));
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int n,m,x,y,blo,cnt; int bel[N],l[500],r[500],num[500],ans; double b[N]; double s[500][500]; void build(){ cnt=n/blo;if(n%blo) cnt++; for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1; for(int i=1;i<=cnt;i++) l[i]=(i-1)*blo+1,r[i]=min(i*blo,n); } void update(int x,int y){ b[x]=1.0*y/x; x=bel[x];num[x]=0;double last=0; for(int i=l[x];i<=r[x];i++) if(b[i]>last){ num[x]++;s[x][num[x]]=b[i];last=b[i]; } last=s[1][num[1]];ans=num[1]; for(int i=2;i<=cnt;i++){ int pos=upper_bound(s[i]+1,s[i]+num[i]+1,last)-s[i]; if(pos>num[i]||pos<1) continue; last=max(last,s[i][num[i]]); ans+=(num[i]-pos+1); } } int main(){ scanf("%d%d",&n,&m);blo=sqrt(n); build(); for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); update(x,y); printf("%d\n",ans); } return 0; }