题意:在一块地上种蔬菜,每种蔬菜有个价值。对于同一块地蔬菜价值高的一定是最后存活,求最后的蔬菜总值。

思路:将蔬菜的价值看做高度的话,题目就转化成求体积并,这样就容易了。
   与HDU 3642 Get The Treasury 同样求体积并,只不过HDU 3642 是要求覆盖大于等于3次的体积并,该题比那道题容易些。

   先将蔬菜价值(即高度)从小到大排序,然后一层一层地开始扫描,计算每层中的面积并,这个就同二维扫描一样。
     然后再用面积乘以这层的高度,即得到该层的体积并。然后所有层的体积加起来,即为所求。

一开始RE。。。
后来仔细看了代码,再看看题意,发现x,y的绝对值小于10^6,也就是有可能为负数,而原本建立了一个数组hashx,
建立x坐标到离散值的映射,之所以RE是因为x<0的话下标就越界了。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid,R using namespace std;
const int maxn=;
int n,m;
int xval[maxn<<]; //存储x坐标
//int hashx[1000005]; //建立横坐标——离散值的映射,一开始没注意题目中说明:x,y的绝对值小于10^6,也就是有可能为负数,不能用hashx
int hashkey[maxn<<]; //建立离散值——坐标的映射,然后用二分搜索对应的离散值
int idx,hidx; //idx为xval数组的下标,hidx用于x坐标的离散化
int price[]; //蔬菜价格 struct Line{
int l,r,y;
int tp; //标记矩形的上边界(tp=-1)和下边界(tp=1)
int hight; //hight为该区域种的蔬菜价值,表示该线条所处的高度范围,0~hight
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn<<]; struct Node{
int cnt;
long long sum;
long long len;
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].cnt=;
tree[rt].len=hashkey[R]-hashkey[L];
tree[rt].sum=;
if(L+==R)
return;
int mid=(L+R)>>;
build(lson);
build(rson);
}
void pushUp(int rt,int L,int R){
if(tree[rt].cnt){
tree[rt].sum=tree[rt].len;
}
else{
if(L+==R){
tree[rt].sum=;
}
else{
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
}
}
}
void update(int rt,int L,int R,int l,int r,int c){
if(l<=L&&R<=r){
tree[rt].cnt+=c;
pushUp(rt,L,R);
return;
}
int mid=(L+R)>>;
if(l<mid)
update(lson,l,r,c);
if(r>mid)
update(rson,l,r,c); /*
if(r<=mid)
update(lson,l,r,c);
else if(l>=mid)
update(rson,l,r,c);
else{
update(lson,l,mid,c);
update(rson,mid,r,c);
}
*/
pushUp(rt,L,R);
}
int binarySearch(int m){
int l=,r=hidx+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashkey[mid]<=m)
l=mid;
else
r=mid;
}
return l;
}
int main()
{
int t;
int x1,y1,x2,y2,s;
scanf("%d",&t);
for(int q=;q<=t;q++){
scanf("%d%d",&n,&m);
memset(price,,sizeof(price));
for(int i=;i<=m;i++){
scanf("%d",&price[i]);
}
idx=-;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&s);
line[*i-].l=x1;line[*i-].r=x2;line[*i-].y=y1;line[*i-].hight=price[s];line[*i-].tp=;
line[*i].l=x1;line[*i].r=x2;line[*i].y=y2;line[*i].hight=price[s];line[*i].tp=-;
xval[++idx]=x1;
xval[++idx]=x2;
}
n*=;
sort(line+,line+n+);
sort(xval,xval+idx+);
hidx=;
//hashx[xval[0]]=hidx;
hashkey[hidx]=xval[];
for(int i=;i<=idx;i++){
if(xval[i]!=xval[i-]){
//hashx[xval[i]]=++hidx; xval[i]有可能为负数啊!!!所以才导致RE。。。
hashkey[++hidx]=xval[i];
}
} long long ans=;
int a,b;
sort(price+,price+m+);
long long sum=;
//枚举每一层
for(int w=;w<=m;w++){
int last=;
long long s=; //该层的面积
build(,,hidx); //是在这里build,一开始写在外层循环外面了。。。
for(int i=;i<=n;i++){
if(line[i].hight>=price[w]){
s+=tree[].sum*(line[i].y-line[last].y);
a=binarySearch(line[i].l);
b=binarySearch(line[i].r);
update(,,hidx,a,b,line[i].tp);
last=i;
}
}
sum+=s*(price[w]-price[w-]); //该层的体积
} printf("Case %d: %I64d\n",q,sum);
}
return ;
}

HDU 3255 Farming (线段树+扫面线,求体积并)的更多相关文章

  1. hdu 3255 Farming(扫描线)

    题目链接:hdu 3255 Farming 题目大意:给定N个矩形,M个植物,然后给定每一个植物的权值pi,pi表示种植物i的土地,单位面积能够收获pi,每一个矩形给定左下角和右上角点的坐标,以及s, ...

  2. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  3. hdu 4288 离线线段树+间隔求和

    Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  4. hdu 3016 dp+线段树

    Man Down Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  5. HDU 5877 dfs+ 线段树(或+树状树组)

    1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au, ...

  6. HDU 4638-Group(线段树+离线处理)

    题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号, ...

  7. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

  8. HDU 2795 Billboard (线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题目大意:有一块h*w的矩形广告板,要往上面贴广告;   然后给n个1*wi的广告,要求把广告贴 ...

  9. hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值

    Conturbatio Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=54 ...

随机推荐

  1. 《Prism 5.0源码走读》Service Locator Pattern

    在Prism Bootstrapper里面取实例的时候使用 ServiceLocator模式,使用的是CommonServiceLocator库 (http://commonservicelocato ...

  2. kettle发送邮件

    使用kettle发送邮件是为了更好的监控ETL的加载信息 以下是我通过测试的一个案例 1. JOB示意图 2.邮件发送配置详细信息 2.1地址信息配置 2.2 服务器信息配置 上图中所说的" ...

  3. 说说oracle中的面向对象与面向集合

    这一篇算是对近期自己学习的一个心得总结 一.oracle的面向对象 SQL是面向集合的这个大家都知道,但是不可否认现在的oracle中有很多地方都体现着面向对象的思维.(这也算是各大语言殊途同归的一个 ...

  4. 1.Knockout.Js(简介)

    前言 最近一段时间在网上经常看到关于Knockout.js文章,于是自己就到官网看了下,不过是英文的,自己果断搞不来,借用google翻译了一下.然后刚刚发现在建立asp.net mvc4.0的应用程 ...

  5. Mysql去除重复

    常用的有两种方法,第一种就是select distinct name from table.但是有时候我们要返回多个字段时就用第二种方法select *, count(distinct name) f ...

  6. PBOC电子钱包与电子现金及QPBOC

    电子钱包:EP 电子现金:EC,在PBOC规范中的13部分定义了<基于借贷记应用的小额支付规范中> QPBOC:在PBOC规范的12部分中定义了<费接触式IC卡支付规范> PB ...

  7. js基础知识点(只有点)

    转自:2015年12月的文章 http://blog.csdn.net/u014326381/article/details/50176339 JavaScript: 作用域链.闭包.运行时上下文.t ...

  8. 通过HTML5获取当前位置

    // 当前位置 function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPositi ...

  9. 2. ProGit-Git基础

    (1) 取得项目的Git仓库 从工作目录中初始化新仓库 git init 从现有仓库克隆 git clone ssh协议 http协议 (2) 检查当前文件状态     git status (3) ...

  10. foj 2044 1 M possible 二进制压缩

    题目链接: http://acm.fzu.edu.cn/problem.php?pid=2044 题意:  给出 一大堆数,找出2个出现次数模3 为1 的两个数字   题解: 把一个数分为几位拆开统计 ...