bzoj2957樓房重建——線段樹
阿新 • • 發佈:2018-04-28
bzoj ons include HR scan geo add style print
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2957
線段樹維護原點到樓頂的斜率,可以知道答案就是從原點開始斜率遞增的個數;
記錄一個mx數組表示這一段上最大的斜率,二分,分類討論,遞歸求解;
而且如果要取rs的長度,不是直接取tr[rs],而是總長度減去tr[ls],因為不能從右邊一段的起點開始……
代碼如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const MAXN=100005; intn,m,tr[MAXN<<2]; double xl[MAXN],mx[MAXN<<2]; int find(int x,int l,int r,double w) { if(l==r)return xl[l]>w; int ls=(x<<1),rs=(x<<1|1); int mid=((l+r)>>1); if(mx[ls]>w)return tr[x]-tr[ls]+find(ls,l,mid,w); return find(rs,mid+1,r,w); } void pushup(intx,int l,int r) { int mid=((l+r)>>1); int ls=(x<<1),rs=(x<<1|1); if(mx[ls]>=mx[rs])tr[x]=tr[ls],mx[x]=mx[ls]; else if(mx[ls]<xl[mid+1])tr[x]=tr[ls]+tr[rs],mx[x]=mx[rs]; else { tr[x]=tr[ls]+find(rs,mid+1,r,mx[ls]); mx[x]=mx[rs]; } }void add(int nw,int L,int R,int l,int r,double w) { if(l==r) { tr[nw]=1;mx[nw]=w;//!!!註意別把nw寫成l return; } int mid=((l+r)>>1); if(mid>=L)add(nw<<1,L,R,l,mid,w); if(mid<R)add(nw<<1|1,L,R,mid+1,r,w); pushup(nw,l,r); } int main() { scanf("%d%d",&n,&m); for(int i=1,x;i<=m;i++) { double y; scanf("%d%lf",&x,&y); xl[x]=y/x; add(1,x,x,1,n,xl[x]); printf("%d\n",tr[1]); } return 0; }
bzoj2957樓房重建——線段樹