4 4
1 6
1 3
3 6
2 4
1 2 0
1 3 1
2 4 2
1 6 3
0
0
0
12
我喜歡左閉右閉的線段樹。。。。
本質是水題,無奈我比這個題還水,被這個題坑了一晚上,最後發現是個SB的錯誤。。。。
有一些磚塊從很高的地方往下掉。在一些特定高度的地方有一些木板,如果磚塊掉到了木板上,就會停住,而那些沒有掉上來的就會繼續往下掉。。。
最後輸出每塊板上各有多少的磚塊。
做法:先將所有的磚塊插入線段樹,然後再逐條插入木板,從高到低。。
每詢問完一條木板,就將當前區間清空。
資料範圍很大,肯定要離散化,不過離散化之後要注意維護兩個點之間的距離,類似於掃描線的做法,離散化後用 x 這個點表示[x,x+1]的距離,因為線段樹的本質是點樹,這些細節的東西一定要想清楚,不然會被坑的很慘。
比如範例的 1 3 5 7 8 離散化後變成了0 1 2 3 4
比如[0,4]分成[0,2] [3,4]兩個子區間,一步小心就會漏掉【2,3】這個區間
其實我們只要嚴格的劃分一下就不存在什麼邊界問題了。。。。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long lld;const int maxn = 100010;lld sum[1<<20];lld col[1<<20];bool flag[1<<20];void build(int l,int r,int rt) {sum[rt] = col[rt] = 0;flag[rt] = false;if(l == r) return ;int m = l + r >> 1;build(lson);build(rson);}int a[maxn*4];void pushdown(int rt,int l,int r) {int m = l + r >> 1;if(col[rt]) {col[rt<<1] += col[rt];col[rt<<1|1] += col[rt];sum[rt<<1] += (lld)col[rt] * (a[m+1]-a[l]);sum[rt<<1|1] += (lld)col[rt] * (a[r+1]-a[m+1]);col[rt] = 0;}}void update(int L,int R,int val,int l,int r,int rt){if(L <= l && r <= R) {col[rt] += val;sum[rt] += val * (a[r+1]-a[l]);return ;}pushdown(rt,l,r);int m = l + r >> 1;if(L <= m) update(L,R,val,lson);if(R > m) update(L,R,val,rson);sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void updatef(int L,int R,int l,int r,int rt){if(flag[rt]) return ;if(L <= l && r <= R){flag[rt] = true;sum[rt] = 0; return ;}pushdown(rt,l,r);int m = l + r >> 1;if(L <= m) updatef(L,R,lson);if(R > m) updatef(L,R,rson); sum[rt] = sum[rt<<1] + sum[rt<<1|1];}lld query(int L,int R,int l,int r,int rt) {if(flag[rt]) return 0;if(L <= l && r <= R) {return sum[rt];}pushdown(rt,l,r);int m = l + r >> 1;lld ret = 0;if(L <= m) ret += query(L,R,lson);if(R > m) ret += query(L,R,rson);return ret;}struct brick {int l,r,lid,rid;}in[maxn];struct board {int l,r,h,lid,rid;int id;bool operator < (const board & cmp) const {return h > cmp.h;}}bo[maxn];int n , m;lld ans[maxn];int main(){while(scanf("%d%d",&n,&m)!=EOF){int tot = 0;for(int i = 0; i < n; i++){ scanf("%d%d",&in[i].l,&in[i].r);a[tot++] = in[i].l;a[tot++] = in[i].r;}for(int i = 0; i < m; i++){scanf("%d%d%d",&bo[i].l,&bo[i].r,&bo[i].h);bo[i].id = i;a[tot++] = bo[i].l;a[tot++] = bo[i].r;}sort(a,a+tot);tot = unique(a,a+tot)-a;for(int i = 0; i < n; i++) {in[i].lid = lower_bound(a,a+tot,in[i].l)-a;in[i].rid = lower_bound(a,a+tot,in[i].r)-a;}for(int i = 0; i < m; i++){bo[i].lid = lower_bound(a,a+tot,bo[i].l)-a;bo[i].rid = lower_bound(a,a+tot,bo[i].r)-a;}build(0,tot-1,1);for(int i = 0; i < n; i ++){update(in[i].lid,in[i].rid-1,1,0,tot-1,1);}sort(bo,bo+m);for(int i = 0; i < m; i++){ans[bo[i].id] = query(bo[i].lid,bo[i].rid-1,0,tot-1,1);updatef(bo[i].lid,bo[i].rid-1,0,tot-1,1);}for(int i = 0; i < m; i++) printf("%lld\n",ans[i]);puts("");}return 0;}/*4 41 61 33 62 41 2 01 3 12 4 21 6 300012*/