2014 UESTC Training for Data Structures D - 长使英雄泪满襟

以下内容来自ShallWe‘s blog

题目

2014 UESTC Training for Data Structures D - 长使英雄泪满襟

看出司马懿在等蜀军粮草不济,孔明于是下令分兵屯田以备久战。司马懿日日只是闭营不出。孔明每日思虑对策至天明,却也无可奈何。漫天星辰中有一类星叫做将星,它们随着将魂的燃烧会越发明亮。今夜五丈原的星空格外璀璨。司马懿一声轻叹。五丈原的星,要落了。

Input

第一行输入三个整数\(n\),\(W\),\(H\),分别表示有\(n\)颗星,矩形宽\(W\),高\(H\)

接下来\(n\)行,每行三个整数,\(x_i\),\(y_i\),\(w_i\)。表示第\(i\)颗星星的在天空的位置是\((x_i,y_i)\),亮度是\(w_i\)
1≤n≤100000,1≤W,H≤1000000,0≤x,y≤100000000,1≤wi≤100

Output

仅一行,该行只包含一个整数,表示平移矩形后,矩形内星星的亮度之和最大能是多少。

解题报告

比较简单的一道扫描线+线段树维护信息的题目。
说说怎么想的,首先,由于矩形的长\(w\),宽\(h\)都是已知的,所以只要固定右下点(当然也可以是别的)那矩形可以控制的stars就是确定的。
比较容易想到的是分别考虑\(x\),\(y\),首先解决\(y\),可以使用扫描线,形象些就是从左向右移动矩形的左边,这样,对于按照\(y\)排序的星星,\(O(n)\)就可以确定哪些在矩形的左右范围内(对于当前左边)。
此时再来处理\(x\),考虑每个星星可以为哪些位置的右下点提供价值,很显然就是一个连续的区间\([x,x+len-1]\)其中,\(len\bf\)是离散化后预处理出来的。所以,当一个星星加入矩形,就是要添加一条线段,使用线段树区间修改全局max来支持操作。

代码

#include <iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
using namespace std;
const int N=10001;
struct node{
    int l,r,mark,mx;
}	seg[N<<2];
int n,W,H;
struct Star{
    int x,y,w,len;
    bool real;
}	star[N<<1];
bool cmpy(const Star &a,const Star &b){
	return a.y==b.y?a.x<b.x:a.y<b.y;
}
bool cmpx(const Star &a,const Star &b){
	return a.x==b.x?a.y<b.y:a.x<b.x;	
}
void build(int x,int l,int r){
    seg[x].l=l;seg[x].r=r;
    if (l==r){
    	seg[x].mx=seg[x].mark=0;
    	return;
	}
	int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
}
void push_down(int x){
    if (seg[x].mark!=0){
        seg[x*2].mark+=seg[x].mark;
        seg[x*2+1].mark+=seg[x].mark;
        seg[x*2].mx+=seg[x].mark;
        seg[x*2+1].mx+=seg[x].mark;
        seg[x].mark=0;
    }
    return;
}
void add(int l,int r,int x,int val){
    bool b=false;
    if (seg[x].l==seg[x].r){
		seg[x].mx+=val;
		return;
	}
    if (seg[x].l==l&&seg[x].r==r){
		seg[x].mark+=val;
		seg[x].mx+=val;
		return;
	}
    push_down(x);
    int mid=(seg[x].l+seg[x].r)>>1;
    if (l>mid){
		add(l,r,x<<1|1,val);b=true;
	}
    if (r<=mid){
		add(l,r,x<<1,val);b=true;
	}
    if (!b) {
        add(l,mid,x*2,val);
        add(mid+1,r,x*2+1,val);
    }
    seg[x].mx=max(seg[x<<1].mx,seg[x<<1|1].mx);
}

int main(){
	freopen("stars.in","r",stdin);
	freopen("stars.out","w",stdout);
    int g,h,j,l;
    while(cin>>n>>W>>H){
   	    memset(seg,0,sizeof(seg));
	    memset(star,0,sizeof(star));
	    for (j=0;j<n;j++) 
			scanf("%d%d%d",&star[j].x,&star[j].y,&star[j].w);
	    sort(star,star+n,cmpy);
	    h=1;g=0;
	    while (g<n){
	        while (g<n && star[g].y==star[g+1].y){
	            star[g].len=h;
	            g++;
	        }
	        star[g].len=h;
	        h++;g++;
	    }
	    g=0;
	    for (j=0;j<n;j++){
	        while (g<n&&star[j].y+H>star[g].y) g++;
	        g--;
	        star[j].y=star[j].len;
	        star[j].len=star[g].len-star[j].len+1;
	    }
	    h=star[n-1].y;
	    for (j=0;j<n;j++){
	        star[j].real=true;
	        star[j+n].x=star[j].x-W;
	        star[j+n].y=star[j].y;
	        star[j+n].w=star[j].w;
	        star[j+n].real=false;
	        star[j+n].len=star[j].len;
	    }
	    sort(star,star+2*n,cmpx);
	    build(1,1,h);
	    int max=-1;
	    for (j=0;j<2*n;j++){
	        if (star[j].real) l=-1;else l=1;
	        add(star[j].y,star[j].y+star[j].len-1,1,l*star[j].w);
	        if (seg[1].mx>max) max=seg[1].mx;
	    }
	    cout<<max<<endl;
	}
    return 0;
}
posted @ 2016-08-11 19:32  ShallWe2000  阅读(207)  评论(0编辑  收藏  举报
Return Top
Dreams writes for dreamers like me.