zoj 3299 线段树 离散化

来源:互联网 发布:淘宝物流管理 编辑:程序博客网 时间:2024/05/17 15:17

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*/



原创粉丝点击