【線段樹】【掃描線】Petrozavodsk Winter Training Camp 2018 Day 5: Grand Prix of Korea, Sunday, February 4, 201

題意:平面上n個點,每一個點帶有一個或正或負的權值,讓你在平面上放一個內邊長爲2l,外邊長爲2r的正方形框,問你最大能圈出來的權值和是多少?spa

容易推出,能框到每一個點的 框中心 的範圍也是一個以該點爲中心的相同大小的框。blog

因而,把每一個點的框拆成4條線。從下往上掃過去,最下面的線,給[R,R]區間加上該點的權值,而後上面再給[L,L]減去,而後上面再給[L,L]加上,而後再往上在給[R,R]減去便可。每次掃完一行,就用線段樹的全局最大值嘗試更新答案。it

兩個坑點:首先,因爲線段樹裏存儲的是離散後的點,因此有可能會存在一些死角,因此給離散化後的每兩個點之間再插入一個點,這樣不會有死角。io

其次,出邊對應的線要向上移動一個單位,而且左右端點向內縮小一個單位,這樣方便處理。class

(UPDATE:雖然AC了此題,可是被HACK了,懷疑是「出邊對應的線要向上移動一個單位,而且左右端點向內縮小一個單位」這裏有BUG)date

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
struct data{
	int p;
	ll v;
}t[1200005];
int a[1200005];
bool cmp(const data &a,const data &b){
	return a.v<b.v;
}
struct LINE{
	int y;
	int l,r;
	int w;
	bool in;
}lines[400005];
bool cm2(const LINE &a,const LINE &b){
	return a.y!=b.y ? a.y<b.y : a.in>b.in;
}
int n,L,R,e,zy;
int y[100005],z[100005],ans;
int maxv[4800005],delta[4800005];
void pushdown(int rt){
	if(delta[rt]){
		delta[rt<<1]+=delta[rt];
		delta[rt<<1|1]+=delta[rt];
		maxv[rt<<1]+=delta[rt];
		maxv[rt<<1|1]+=delta[rt];
		delta[rt]=0;
	}
}
void update(int ql,int qr,int v,int rt,int l,int r){
	if(ql<=l && r<=qr){
		maxv[rt]+=v;
		delta[rt]+=v;
		return;
	}
	int m=(l+r>>1);
	pushdown(rt);
	if(ql<=m){
		update(ql,qr,v,rt<<1,l,m);
	}
	if(m<qr){
		update(ql,qr,v,rt<<1|1,m+1,r);
	}
	maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
int main(){
//	freopen("a.in","r",stdin);
	int x;
	scanf("%d%d%d",&n,&L,&R);
	for(int i=1;i<=n;++i){
		scanf("%d%d%d",&x,&y[i],&z[i]);
		t[++e].v=(ll)(x-R)*2ll;
		t[e].p=e;
		t[++e].v=(ll)(x-R)*2ll-1ll;
		t[e].p=e;
		t[++e].v=(ll)(x-R)*2ll+1ll;
		t[e].p=e;
		
		t[++e].v=(ll)(x-L+1)*2ll;
		t[e].p=e;
		t[++e].v=(ll)(x-L+1)*2ll-1ll;
		t[e].p=e;
		t[++e].v=(ll)(x-L+1)*2ll+1ll;
		t[e].p=e;
		
		t[++e].v=(ll)(x+L-1)*2ll;
		t[e].p=e;
		t[++e].v=(ll)(x+L-1)*2ll-1ll;
		t[e].p=e;
		t[++e].v=(ll)(x+L-1)*2ll+1ll;
		t[e].p=e;
		
		t[++e].v=(ll)(x+R)*2;
		t[e].p=e;
		t[++e].v=(ll)(x+R)*2-1;
		t[e].p=e;
		t[++e].v=(ll)(x+R)*2+1;
		t[e].p=e;
	}
	sort(t+1,t+e+1,cmp);
	a[t[1].p]=++zy;
	for(int i=2;i<=e;++i){
		if(t[i].v!=t[i-1].v){
			++zy;
		}
		a[t[i].p]=zy;
	}
	for(int i=1;i<=n;++i){
		lines[i*4-3].y=y[i]-R;
		lines[i*4-2].y=y[i]-L+1;
		lines[i*4-1].y=y[i]+L;
		lines[i*4-0].y=y[i]+R+1;
		
		lines[i*4-3].l=a[i*12-11];
		lines[i*4-2].l=a[i*12-8];
		lines[i*4-1].l=a[i*12-8];
		lines[i*4-0].l=a[i*12-11];
		
		lines[i*4-3].r=a[i*12-2];
		lines[i*4-2].r=a[i*12-5];
		lines[i*4-1].r=a[i*12-5];
		lines[i*4-0].r=a[i*12-2];
		
		lines[i*4-3].w=z[i];
		lines[i*4-2].w=z[i];
		lines[i*4-1].w=z[i];
		lines[i*4-0].w=z[i];
		
		lines[i*4-3].in=1;
		lines[i*4-2].in=0;
		lines[i*4-1].in=1;
		lines[i*4-0].in=0;
	}
	sort(lines+1,lines+(n<<2|1),cm2);
	for(int i=1;i<=(n<<2);++i){
		if(lines[i].in){
			update(lines[i].l,lines[i].r,lines[i].w,1,1,zy);
		}
		else{
			update(lines[i].l,lines[i].r,-lines[i].w,1,1,zy);
		}
		if(lines[i].y!=lines[i+1].y){
			ans=max(ans,maxv[1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
相關文章
相關標籤/搜索