题意:
有n块板砖从天而降,底下有了m块木板来挡,每块板砖长度为1单位。
现在题目给出连续板砖的范围还有木板的范围与高度,问最后每块木板上有几块板砖。
解析:
这题想了挺久的最后终于搞定了。
线段树的区间更新问题。
由于li和ri比较大(0<=li<ri<=30000000),首先考虑到的是对左右边界进行离散化。然后先按照木板从低到高进行排序,然后对区间进行染色。
然后再把所有的砖块放上去,对区间进行更新,维护一个addv的懒惰标记,代表这个区间被覆盖了多少层。
最后进行到一次直到叶子节点的总查询得到最终答案。
总复杂度O((n+m+tot)log2n)
注意:
这题对内存的要求比较高,开小了会re,开大了会mle。
my code
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
using namespace std;
typedef long long ll;
const int N = 100005;
struct Node {
int ll, rr, lid, rid;
int h, id;
} brick[N], board[N];
int n, m, tot;
int id[N*6];
ll length[N*6], ans[N];
bool cmp(Node a, Node b) {
return a.h < b.h;
}
void discrete() {
sort(id, id+tot);
tot = unique(id, id+tot) - id;
for(int i = 1; i <= n; i++) {
brick[i].lid = lower_bound(id, id+tot, brick[i].ll) - id;
brick[i].rid = lower_bound(id, id+tot, brick[i].rr) - id - 1;
}
for(int i = 1; i <= m; i++) {
board[i].lid = lower_bound(id, id+tot, board[i].ll) - id;
board[i].rid = lower_bound(id, id+tot, board[i].rr) - id - 1;
}
for(int i = 0; i < tot-1; i++) {
length[i] = id[i+1] - id[i];
}
}
ll color[N*12], addv[N*12];
void build(int o, int L, int R) {
color[o] = addv[o] = 0;
if(L == R) return ;
int M = (L + R)/2;
build(lson);
build(rson);
}
void pushDown(int o) {
if(color[o]) {
color[ls] = color[rs] = color[o];
color[o] = 0;
}
if(addv[o]) {
addv[ls] += addv[o]; addv[rs] += addv[o];
addv[o] = 0;
}
}
void setColor(int o, int L, int R, int ql, int qr, int val) {
if(ql <= L && R <= qr) {
color[o] = val;
return ;
}
pushDown(o);
int M = (L + R)/2;
if(ql <= M) setColor(lson, ql, qr, val);
if(qr > M) setColor(rson, ql, qr, val);
}
void modify(int o, int L, int R, int ql, int qr) {
if(ql <= L && R <= qr) {
addv[o]++;
return ;
}
pushDown(o);
int M = (L + R)/2;
if(ql <= M) modify(lson, ql, qr);
if(qr > M) modify(rson, ql, qr);
}
void query(int o, int L, int R) {
if(L == R) {
if(color[o])
ans[color[o]] += addv[o]*length[L];
return ;
}
pushDown(o);
int M = (L + R)/2;
query(lson);
query(rson);
}
int main() {
while(scanf("%d%d", &n, &m) != EOF) {
tot = 0;
for(int i = 1; i <= n; i++) {
scanf("%d%d", &brick[i].ll, &brick[i].rr);
id[tot++] = brick[i].ll;
id[tot++] = brick[i].rr;
}
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &board[i].ll, &board[i].rr, &board[i].h);
id[tot++] = board[i].ll;
id[tot++] = board[i].rr;
board[i].id = i;
}
discrete();
int end = tot-2;
build(1, 0, end);
sort(board+1, board+m+1, cmp);
for(int i = 1; i <= m; i++)
setColor(1, 0, end, board[i].lid, board[i].rid, board[i].id);
for(int i = 1; i <= n; i++)
modify(1, 0, end, brick[i].lid, brick[i].rid);
memset(ans, 0, sizeof(ans));
query(1, 0, end);
for(int i = 1; i <= m; i++)
printf("%lld\n", ans[i]);
puts("");
}
return 0;
}