POJ 2482 Stars in Your Window【离散化+扫描线+线段树

14 篇文章 0 订阅
1 篇文章 0 订阅

听说flaze太久没有更blog了……然而学渣被文化课虐的欲生欲死【假装自己五一没有花一天去ACG展子排队】


学会了离散化的新姿势

顺便感谢cyz大爷帮忙debug【虽然最后发现是flaze写丑了重新码一遍就A了【至于I64d啥的都是浮云【望天默念三声long long mian()

二话不说,上代码。。。

都是套路,第一次写没有inqry的线段树感觉连字都不会打了【


//一直没有写过扫描线……只会口胡……现在终于去水了一道题,感觉自己萌萌哒 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;	int n,W,H;
const int MAXN=10057;

struct t1{
	long long x,y1,y2,l;	//y1是下界,y2是上界,x是横坐标; 
	bool operator < (const t1 xx) const {
//		if(x==xx.x)	return l<xx.l;
		return x<xx.x;
	}
}rec[MAXN<<2];
int y[MAXN<<2],cnt_y;

struct t2{
	long long dt,lzy;
}node[MAXN<<4];

void pushdown(int now){
	node[now<<1].dt+=node[now].lzy,node[now<<1|1].dt+=node[now].lzy;
	node[now<<1].lzy+=node[now].lzy,node[now<<1|1].lzy+=node[now].lzy;
	node[now].lzy=0;
}


//离散化新姿势,线段树用起来有奇效   只要把原来的l,r,mid改成排序后的数组y的下标就好了   嗯感性理解会觉得简直够了 
void Modify(int now,int l,int r,long long L,long long R,long long v){
//	cout<<y[l]<<' '<<y[r]<<' '<<L<<' '<<R<<endl;
	if(L<=y[l]&&y[r]<=R){
		node[now].dt+=v;
		node[now].lzy+=v;
		return ;	
	}	
	pushdown(now);
	int mid=(l+r)>>1;
	if(L<=y[mid])	Modify(now<<1,l,mid,L,R,v);
	if(y[mid+1]<=R)	Modify(now<<1|1,mid+1,r,L,R,v);
	node[now].dt=max(node[now<<1].dt,node[now<<1|1].dt);
}

long long ans;

int main(){
//	freopen("1.txt","r",stdin); 
	while(~scanf("%d%d%d",&n,&W,&H)){
		ans=0;
		memset(rec,0,sizeof(rec));
		cnt_y=0;	
		for(int i=1;i<=n;++i){
			//把星星变成一个面,窗户当成一个点【用心感受x
			//展开的时候,每个rec只记录一条平行于纵坐标的线(矩形就拆成那种左边一个标记右边一个的 
			scanf("%I64d%I64d%I64d",&rec[i].x,&rec[i].y1,&rec[i].l);
			y[2*i-1]=rec[i].y2=rec[i].y1+H-1;
			y[2*i]=rec[i].y1;
			rec[i+n]=rec[i];
			rec[i+n].x=rec[i].x+W;
			rec[i+n].l=-rec[i].l;
		}
		sort(rec+1,rec+2*n+1);
		sort(y+1,y+2*n+1);
		cnt_y=unique(y+1,y+2*n+1)-y-1;
		
		for(int i=1;i<=2*n;++i){
			Modify(1,1,cnt_y,rec[i].y1,rec[i].y2,rec[i].l);
			//对于每个位置,应该是把所有操作做完了才更新答案【所以下面那句】,至于为什么……本来这里应该删掉一些再加上的话,岂不是血崩了【感性理解】 
			if(i == 2 * n || rec[i+1].x!=rec[i].x)
				ans=max(ans,node[1].dt);
				
		}
		
		printf("%I64d\n",ans);
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值