该题和 黑书 P102 采矿 类似

参考链接:
http://blog.csdn.net/shiqi_614/article/details/7819232
http://blog.csdn.net/tsaid/article/details/6686907
http://www.cnblogs.com/372465774y/archive/2012/07/28/2613272.html

题意:
  给你10000以内的星星的坐标和星星的亮度(即分别为x,y,c),要求用W*H的矩形去围住一个区域,
  使得这个区域内的星星的亮度最大,并且要求矩形边框上的星星不计入内。矩形可以平移,但不能旋转。

思路:

  这题我觉得的精妙之处就是将点转化成矩形,即对每一颗星星,画出以它为左下角的矩形,这个矩形就是它的影响范围。
  另外有一点需要注意,题目要求不包括矩形边上的点。
  但其实矩形下边(即y)和矩形左边(即x)这两边的星星可以算入进去,
  而矩形上边(即y+h)和矩形右边(即x+w)这两边的星星不能被算入。
  原因是只要把矩形往左下角移动那么一点点,就把下边和左边上的星星给包括进去了。
  因此一颗星星(x,y),它所能影响到的矩形的横轴区间为[x,x+w-1],纵轴区间为[y,y+h-1]

  所以为了方便处理,我们将每一颗星建立两条线line1(x,y,y+h-1,c),line2(x+w,y,y+h-1,-c)
  这样当我们不断插入星星的时候,其实就相当于有一个矩形框在从左往右移动,因为碰到 line1 则对应的影响区间[y,y+h-1]总亮度加上c,说明矩形中包含了该星星。
  碰到 line2 则再加上 -c, 那么 c + (-c ) = 0, 相当于该星星已不在矩形框内。
  那么,我们每插入一颗星就得到一个 宽度范围 固定(即w),但是 高度范围 不定(即h)的矩形。
  如此便只需要维护 y 坐标这一个变量了,让 [y,y+h-1] 这一区间加上c, 用线段树求得此时刻的最大值。
  当所有星星都插入完成,得到的最大值也就是我们要求的值了。

  还有一点是,对于排序的时候,若x相同,-c的要先放在前面。因为如果优先+c的边,
  那么位于x处的星星就会影响到x+w,而实际它是不能算入的。

  最后注意:数据会超int,所以类型要设成long long

第一次写的代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R using namespace std;
const int maxn=;
int n,w,h;
long long x,y,val;
long long yy[maxn]; //存储纵坐标的值
int idx; //yy数组的下标
map<long long,int> hashy; //纵坐标y的映射
int cnt; //离散值 struct Line{
long long x,y1,y2; //y1=y,y2=y+h-1
long long c; //亮度
//按照x从小到大排序,若x相同,则c小的(即-c)排在前面
bool operator<(const Line tmp)const{
if(x==tmp.x)
return c<tmp.c;
else
return x<tmp.x;
}
}line[maxn]; struct Node{
long long sum; //存储该区间中的最大值
long long add;
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].sum=tree[rt].add=;
if(L==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
}
void pushUp(int rt){
tree[rt].sum=max(tree[rt<<].sum,tree[rt<<|].sum);
}
void pushDown(int rt){
if(tree[rt].add){
tree[rt<<].add+=tree[rt].add;
tree[rt<<|].add+=tree[rt].add;
tree[rt<<].sum+=tree[rt].add;
tree[rt<<|].sum+=tree[rt].add;
tree[rt].add=;
}
}
void update(int rt,int L,int R,int l,int r,long long c){
if(l<=L&&R<=r){
tree[rt].sum+=c;
tree[rt].add+=c;
return;
}
pushDown(rt);
int mid=(L+R)>>;
if(l<=mid)
update(lson,l,r,c);
if(r>mid)
update(rson,l,r,c);
pushUp(rt);
} int main()
{
while(scanf("%d%d%d",&n,&w,&h)!=EOF){
idx=-;
for(int i=;i<=n;i++){
scanf("%I64d%I64d%I64d",&x,&y,&val);
line[*i-].x=x;line[*i-].y1=y;line[*i-].y2=y+h-;line[*i-].c=val;
line[*i].x=x+w;line[*i].y1=y;line[*i].y2=y+h-;line[*i].c=-val;
yy[++idx]=y;
yy[++idx]=y+h-;
}
sort(yy,yy+idx+);
//对y进行离散化
cnt=;
hashy[yy[]]=++cnt;
for(int i=;i<=idx;i++){
if(yy[i]!=yy[i-])
hashy[yy[i]]=++cnt;
}
n*=;
sort(line+,line+n+);
long long ans=;
build(,,cnt);
//将星星一颗一颗地插入
for(int i=;i<=n;i++){
update(,,cnt,hashy[line[i].y1],hashy[line[i].y2],line[i].c);
ans=max(tree[].sum,ans);
}
printf("%I64d\n",ans); }
return ;
}

后来又重写了一遍,没用map,用的是离散化+二分查找离散值

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
using namespace std;
const int maxn=+;
int n,w,h;
int cnty,idy;
long long hashy[maxn<<]; struct Line{
long long x,y1,y2;
int c;
bool operator<(const Line tmp)const{
if(x==tmp.x){
return c<tmp.c;
}
else{
return x<tmp.x;
}
}
}line[maxn<<]; struct Node{
long long sum;
long long add;
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].sum=tree[rt].add=;
if(L==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
}
void pushUp(int rt){
tree[rt].sum=max(tree[rt<<].sum,tree[rt<<|].sum);
}
void pushDown(int rt){
if(tree[rt].add){
tree[rt<<].add+=tree[rt].add;
tree[rt<<|].add+=tree[rt].add;
tree[rt<<].sum+=tree[rt].add;
tree[rt<<|].sum+=tree[rt].add;
tree[rt].add=;
}
} void update(int rt,int L,int R,int l,int r,int c){
if(l<=L&&R<=r){
tree[rt].add+=c;
tree[rt].sum+=c;
return;
}
pushDown(rt);
int mid=(L+R)>>;
if(l<=mid)
update(lson,l,r,c);
if(r>mid)
update(rson,l,r,c);
pushUp(rt);
}
int binarySearch(long long x){
int l=,r=idy+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashy[mid]<=x)
l=mid;
else
r=mid;
}
return l;
}
int main()
{
long long x,y,c;
while(scanf("%d%d%d",&n,&w,&h)!=EOF){
cnty=;
for(int i=;i<=n;i++){
scanf("%lld%lld%lld",&x,&y,&c);
line[*i-].x=x;line[*i-].y1=y;line[*i-].y2=y+h-;line[*i-].c=c;
line[*i].x=x+w;line[*i].y1=y;line[*i].y2=y+h-;line[*i].c=-c;
hashy[cnty++]=y;
hashy[cnty++]=y+h-;
}
n=n*;
sort(hashy+,hashy+cnty);
idy=;
for(int i=;i<cnty;i++){
if(hashy[i]!=hashy[i-])
hashy[++idy]=hashy[i];
}
sort(line+,line+n+);
build(,,idy);
long long ans=;
int a,b;
for(int i=;i<=n;i++){
a=binarySearch(line[i].y1);
b=binarySearch(line[i].y2);
update(,,idy,a,b,line[i].c);
ans=max(tree[].sum,ans);
}
printf("%I64d\n",ans);
}
return ;
}

POJ 2482 Stars in Your Window (线段树+扫描线+区间最值,思路太妙了)的更多相关文章

  1. POJ 2482 Stars in Your Window 线段树扫描线

    Stars in Your Window   Description Fleeting time does not blur my memory of you. Can it really be 4 ...

  2. POJ 2482 Stars in Your Window(线段树+扫描线)

    题目链接 非常不容易的一道题,把每个点向右上构造一个矩形,将问题转化为重合矩形那个亮度最大,注意LL,注意排序. #include <cstdio> #include <cstrin ...

  3. POJ 2482 Stars in Your Window 线段树

    如果按一般的思路来想,去求窗户能框住的星星,就很难想出来. 如果换一个思路,找出每颗星星能被哪些窗户框住,这题就变得非常简单了. 不妨以每个窗户的中心代表每个窗户,那么每颗星星所对应的窗户的范围即以其 ...

  4. POJ 2482 Stars in Your Window (线段树区间合并+扫描线)

    这题开始一直被矩形框束缚了,想法一直都是枚举线,但是这样枚举都需要O(n^2)...但是看了别人的思路,感觉这题思想真心很好(PS:开头好浪漫的描述啊,可惜并没有什么用)  题意就是在平面上给你一些星 ...

  5. 【POJ-2482】Stars in your window 线段树 + 扫描线

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11706   Accepted:  ...

  6. poj 2482 Stars in Your Window + 51Nod1208(扫描线+离散化+线段树)

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13196   Accepted:  ...

  7. POJ 2482 Stars in Your Window(线段树)

    POJ 2482 Stars in Your Window 题目链接 题意:给定一些星星,每一个星星都有一个亮度.如今要用w * h的矩形去框星星,问最大能框的亮度是多少 思路:转化为扫描线的问题,每 ...

  8. poj 2482 Stars in Your Window(扫描线)

    id=2482" target="_blank" style="">题目链接:poj 2482 Stars in Your Window 题目大 ...

  9. xdoj-1324 (区间离散化-线段树求区间最值)

    思想 : 1 优化:题意是覆盖点,将区间看成 (l,r)转化为( l-1,r) 覆盖区间 2 核心:dp[i]  覆盖从1到i区间的最小花费 dp[a[i].r]=min (dp[k])+a[i]s; ...

随机推荐

  1. WPF动画 storyboard

    <Window x:Class="StoryBoard.MainWindow" xmlns="http://schemas.microsoft.com/winfx/ ...

  2. 刀哥多线程GCD核心概念gcd

    GCD GCD 核心概念 将任务添加到队列,并且指定执行任务的函数 任务使用 block 封装 任务的 block 没有参数也没有返回值 执行任务的函数 异步 dispatch_async 不用等待当 ...

  3. [转]PROC简单使用用例--VC连接ORACLE

    [转]PROC简单使用用例--VC连接ORACLE 操作系统:windows 7 数据库版本:oracle 10g VS版本:VS2010 前言:连接ORACLE的方式有很多,此处仅以PROC为例,说 ...

  4. 算法系列3《SHA》

    SHA是一种数据加密算法,该算法经过加密专家多年来的发展和改进已日益完善,现在已成为公认的最安全的散列算法之一,并被广泛使用.该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小 ...

  5. oracle 11g 表空间使用率

    Oracle数据库表空间使用量查询: select b.file_name 物理文件名,b.tablespace_name 表空间,b.bytes/1024/1024 大小M,(b.bytes-sum ...

  6. 调整maven配置文件

    maven的配置文件位置:maven安装位置\conf\settings.xml. 这次调整maven的配置文件主要解决三个问题: 调整本地依赖库位置 设置代理 添加远程资源库镜像节点 调整本地依赖库 ...

  7. [转]webrtc学习: 部署stun和turn服务器

    [转]webrtc学习: 部署stun和turn服务器 http://www.cnblogs.com/lingdhox/p/4209659.html webrtc的P2P穿透部分是由libjingle ...

  8. As.net WebAPI CORS, 开启跨源访问,解决错误No 'Access-Control-Allow-Origin' header is present on the requested resource

    默认情况下ajax请求是有同源策略,限制了不同域请求的响应. 例子:http://localhost:23160/HtmlPage.html 请求不同源API http://localhost:228 ...

  9. Qt中的事件

    1. 引自---http://blog.sina.com.cn/s/blog_6e80f1390100pro4.html 信号和事件的区别就在与,事件比信号更加底层,而且如果一个信号对应多个槽的话,信 ...

  10. 【BZOJ 2324】 [ZJOI2011]营救皮卡丘

    Description 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路. 火箭队一共有N个据点,据点 ...