1. 程式人生 > >bzoj2957: 樓房重建,分塊

bzoj2957: 樓房重建,分塊

eps name post 題目 開始 iostream 暴力 body gpo

題目鏈接:2957: 樓房重建

分塊沒學過的可以看,分塊入門。

題解:把房子分成√n塊每塊裏面維護一個遞增的子序列,每次更新之後,在每一個小塊內二分查找第一個大於前面最大的斜率,開始斜率為0,每次找完一塊更新一次,暴力加進答案。

#include<bits/stdc++.h>
#include<set>
#include<iostream>
#include<string>
#include<iomanip>
#include<vector>
#include<cmath>
#include
<cstdio> #include<cstring> #include<algorithm> #define pb push_back #define mp make_pair #define ll long long #define PI 3.14159265 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define eps 1e-7 typedef unsigned long long ull; const int mod=1e9+7; const int maxn=1e5+5
; const ll inf=0x3f3f3f3f; const int block=550; using namespace std; struct bloc { int cnt; double s[1000]; }a[1000]; int n,m,num,belong[maxn],l[maxn],r[maxn]; double y;int x; double xl[maxn]; void built() { num=n/block;if(n%block)num++; for(int i=1;i<=n;i++) { belong[i]
=((i-1)/block)+1; } for(int i=1;i<=num;i++) { l[i]=(i-1)*block+1;r[i]=i*block; } r[num]=n; } int slove(int x,double y) { xl[x]=(double)y/x;int p=belong[x]; double last=0.0; int cnt=0; for(int i=l[p];i<=r[p];i++) { if(xl[i]>last)last=a[p].s[cnt++]=xl[i]; } a[p].cnt=cnt; int ans=a[1].cnt;last=a[1].s[a[1].cnt-1]; for(int i=2;i<=num;i++) { int p=0; p=upper_bound(a[i].s,a[i].s+a[i].cnt,last)-a[i].s; ans+=(a[i].cnt-p); last=max(a[i].s[a[i].cnt-1],last); } return ans; } int main() { scanf("%d %d",&n,&m); built(); while(m--) { scanf("%d %lf",&x,&y); printf("%d\n",slove(x,y)); } return 0; }

bzoj2957: 樓房重建,分塊