题目链接:传送门
题目大意:
我们要在地平线(看成数轴)上依次建造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;
}