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|1 typedef 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 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 */
作者:haha593572013 发表于2013-3-29 11:45:50 原文链接
阅读:41 评论:0 查看评论