1.題目描述:點擊打開鏈接
2.解題思路:本題用線段樹解決。根據題意,我們需要構造一棵線段樹,維護區間[L,R)中的長度和這段區間的高度值。不過在pushup的時候,只有左孩子和右孩子都相同時候,才更新當前的區間高度,因爲我們要維護的是這段區間確切的高度值,而不是最大值或最小值。這樣,只需要邊輸入邊累加答案即可。總的時間複雜度爲O(NlogC)。
3.代碼:
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define rep(i,n) for(int i=0;i<(n);i++)
#define me(s) memset(s,0,sizeof(s))
#define pb push_back
#define lid (id<<1)
#define rid (id<<1|1)
typedef long long ll;
typedef pair<int,int> P;
const int N = 100000 + 10;
struct Node
{
int l, r;
int val;
int len;
int mid() { return l + (r - l) / 2; }
}tr[N << 2];
void pushup(int id)
{
if (tr[lid].val > 0 && tr[rid].val > 0 && tr[lid].val == tr[rid].val)
tr[id].val = tr[lid].val;
}
void pushdown(int id)
{
if (tr[id].val)
{
tr[lid].val = tr[id].val;
tr[rid].val = tr[id].val;
tr[id].val = 0;
}
}
void build(int id, int L, int R)
{
tr[id].l = L, tr[id].r = R;
tr[id].val = 0;
tr[id].len = R - L;
if (L + 1 == R)return;
int mid = tr[id].mid();
build(lid, L, mid);
build(rid, mid, R);
}
int query(int id, int L, int R, int val)
{
int l = tr[id].l, r = tr[id].r;
if ((L <= l&&r <= R&&tr[id].val>0) || l + 1 == r)
{
if (tr[id].val <= val)
{
tr[id].val = val;
return tr[id].len;
}
return 0;
}
pushdown(id);
int mid = tr[id].mid();
int s1 = 0, s2 = 0;
if (L<mid)s1 = query(lid, L, R, val);
if (R >mid)s2 = query(rid, L, R, val);
pushup(id);
return s1 + s2;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n;
scanf("%d", &n);
build(1, 1, 100000 + 10);
int l, r, h;
int ans = 0;
for (int i = 0; i<n; i++)
{
scanf("%d%d%d", &l, &r, &h);
ans += query(1, l, r, h);
}
printf("%d\n", ans);
}
scanf("%d", &T);
return 0;
}