题意:
要在地平线上依次修建n座建筑物,建筑物的修建顺序按照从后往前的顺序,因此新建建筑物可能会挡住一部分老建筑物。
修建完一座后统计他有多长的部分是最高的(可以并列最高)。求所有建筑物该长度的总和。
之前看过这个题,但是没有思路,当时的想法是离线按照高度处理,但是这有复杂度太高。
今天再看这个题的时候突然就想到了做法
直接维护区间的建筑物高度,比如
初始的时候全部区间都为高度为0,有两座建筑物:
5 11 3 结果是 [5, 10](把区间变成点,[x, x+1]用区间的左端点x表示)高度为3
1 10 1 结果是[1, 4]高度为1,[5, 10]高度为3。
也就是 set [L, R]为v的时候,只有当区间的setv小于v的才set
这样答案就是[L, R]中setv比v大的区间长度
然后这样交上去TLE了,然后一想这样一次操作复杂度可达到O(n*4)(线段树节点总数),因为当1-n的高度分别为1-n的时候就会出现这种极端情况。
然后加了一个minv维护区间的最小值,如果最小值都比当前高度大,那么这个区间肯定会遮挡当前建筑物。就不用递归下去了
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
const int maxo = maxn * 4;
int setv[maxo];
int minv[maxo];
void pushDown(int o) {
if(setv[o] != -1) {
minv[o<<1] = setv[o<<1] = setv[o<<1|1] = setv[o];
setv[o] = -1;
}
}
void pushUp(int o) {
minv[o] = min(minv[o*2], minv[o*2+1]);
}
int ql, qr, qv, _qans;
void update(int o, int L, int R) {
if(ql <= L && R <= qr) {
if(setv[o] != -1) {
if(setv[o] > qv) {
_qans += R - L + 1;
} else {
setv[o] = qv;
}
minv[o] = setv[o];
return ;
}
if(minv[o] > qv) {
_qans += R - L + 1;
return ;
}
}
pushDown(o);
int M = L + (R-L) / 2;
if(ql <= M) update(o<<1, L, M);
if(M < qr) update(o<<1|1, M+1, R);
pushUp(o);
}
int qls[maxn], qrs[maxn], qvs[maxn];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
int maxL = 0;
memset(setv, -1, sizeof(setv));
memset(minv, 0, sizeof(minv));
setv[1] = 0;
scanf("%d", &n);
for(int i=0; i<n; i++) {
scanf("%d%d%d", &qls[i], &qrs[i], &qvs[i]);
maxL = max(maxL, qrs[i]);
}
maxL = maxL + 2;
LL ans = 0;
for(int i=0; i<n; i++) {
_qans = 0;
ql = qls[i], qr = qrs[i] - 1, qv = qvs[i];
update(1, 1, maxL);
ans += qrs[i] - qls[i] - _qans;
}
P64I(ans);
}
scanf("%*d");
return 0;
}