题目链接:传送门
题目大意:
我们要在地平线(看成数轴)上依次建造n座建筑物。建筑物的修建按照从后往前的顺序,因此新建筑物可能会挡住一部分老建筑物。
修建完一座建筑物后,统计它在多长的部分最长(可以和其他建筑物并列最高),并把这个长度称为“覆盖度”。
求所有建筑物的总覆盖度。
代码:
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> using namespace std; #define lchild (rt<<1) #define rchild (rt<<1|1) typedef long long llt; const int N = 100010; const int M = 50010; const int INF = 0x3fffffff; int Max[N<<2],lazy[N<<2],ans; void init() { ans = 0; memset(lazy,0,sizeof(lazy)); memset(Max,0,sizeof(Max)); } void PushUp(int rt) { Max[rt] = max(Max[lchild],Max[rchild]); } void PushDown(int rt) { lazy[lchild] = max(lazy[lchild],lazy[rt]); lazy[rchild] = max(lazy[rchild],lazy[rt]); } void Update(int L,int R,int C,int l,int r,int rt) { if(lazy[rt] > C) return; if(L <= l && r <= R && C >= Max[rt]){ ans += r-l+1; Max[rt] = C; lazy[rt] = C; return; } if(l == r) return; int m = (l+r)>>1; PushDown(rt); if(L <= m) Update(L,R,C,l,m,lchild); if(R > m) Update(L,R,C,m+1,r,rchild); PushUp(rt); } int main() { // freopen("D:\\06.in","r",stdin); // freopen("D:\\data.txt","w",stdout); int T; scanf("%d",&T); while(T--){ init(); int n,a,b,c; scanf("%d",&n); for(int i = 0; i < n; ++i){ scanf("%d%d%d",&a,&b,&c); Update(a,b-1,c,1,N-1,1); } printf("%d\n",ans); } scanf("%d",&T); return 0; }