Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

zoj 3299 线段树 离散化

$
0
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

我喜欢左闭右闭的线段树。。。。

本质是水题,无奈我比这个题还水,被这个题坑了一晚上,最后发现是个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 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>