【洛谷】P4198 楼房重建
2018-11-05 20:27
246 查看
题解
我们转而维护每个点的斜率,显然一个楼房能被看见它就是一个前缀最大值,斜率比较为了节约精度可以用向量替代
我们每个区间维护被看到的楼房的个数,和楼房的最大值,叶子节点在有楼房时,值为1
那么考虑合并两个区间,左节点的所有能被看到的楼房还是能被看到,右边节点能看到的楼房的斜率需要大于左边节点所需要的斜率最大值
为了找到这些我们去右节点的左右区间去找
如果这个值\(P\)大于等于区间左边的最大值,那么这个值要在右边找
如果小于的话,加上右边的大小,即\(tr[u].cnt - tr[u << 1].cnt\),然后递归到左边处理
复杂度\(O(n \log^2 n)\)
代码
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } struct Point { int64 x,y; Point(int64 _x = 0,int64 _y = 0) { x = _x;y = _y; } friend Point operator + (const Point &a,const Point &b) { return Point(a.x + b.x,a.y + b.y); } friend Point operator - (const Point &a,const Point &b) { return Point(a.x - b.x,a.y - b.y); } friend int64 operator * (const Point &a,const Point &b) { return a.x * b.y - a.y * b.x; } friend bool operator < (const Point &a,const Point &b) { return a * b > 0; } friend bool operator > (const Point &a,const Point &b) { return a * b < 0; } friend bool operator == (const Point &a,const Point &b) { return a * b == 0; } friend bool operator >= (const Point &a,const Point &b) { return a > b || a == b; } friend bool operator <= (const Point &a,const Point &b) { return a < b || a == b; } }; struct node { int L,R,cnt;Point P; }tr[MAXN * 4]; int N,M; void build(int u,int l,int r) { tr[u].L = l;tr[u].R = r;tr[u].cnt = 0; tr[u].P = Point(r,0); if(l == r) return; int mid = (l + r) >> 1; build(u << 1,l,mid); build(u << 1 | 1,mid + 1,r); } int Calc(int u,Point P) { if(tr[u].L == tr[u].R) return tr[u].P > P; if(P >= tr[u << 1].P) { return Calc(u << 1 | 1,P); } else { return Calc(u << 1,P) + tr[u].cnt - tr[u << 1].cnt; } } void Change(int u,int pos,int y) { if(tr[u].L == tr[u].R) { tr[u].P = Point(pos,y); if(!y) tr[u].cnt = 0; else tr[u].cnt = 1; return; } int mid = (tr[u].L + tr[u].R) >> 1; if(pos <= mid) Change(u << 1,pos,y); else Change(u << 1 | 1,pos,y); tr[u].P = max(tr[u << 1].P,tr[u << 1 | 1].P); tr[u].cnt = tr[u << 1].cnt + Calc(u << 1 | 1,tr[u << 1].P); } void Solve() { read(N);read(M); build(1,1,N); int x,y; for(int i = 1 ; i <= M ; ++i) { read(x);read(y); Change(1,x,y); out(tr[1].cnt);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
相关文章推荐
- P4198 楼房重建
- P4198 楼房重建
- BZOJ2957 楼房重建
- 【Bzoj2957】楼房重建
- bzoj2957:楼房重建
- AC日记——灾后重建 洛谷 P1119
- BZOJ_2957_楼房重建_线段树
- [BZOJ 2957] 楼房重建 线段树/分块(两种做法)
- BZOJ 2957 楼房重建(线段树)(思路)
- 洛谷 1119 灾后重建 Floyd
- 洛谷P3905 道路重建
- Bzoj 2957: 楼房重建(线段树)
- bzoj2957: 楼房重建【线段树】
- 【BZOJ 2957】 2957: 楼房重建 (线段树)
- 【BZOJ2957】楼房重建(线段树)
- BZOJ2957: 楼房重建 题解
- [Luogu P4198]楼房重建(线段树)
- 【BZOJ—2957楼房重建】【连载:请在T台上微笑】
- BZOJ 2957 楼房重建(线段树)(思路)
- bzoj 2957: 楼房重建