hdu 4052 线段树扫描线、奇特处理
Adding New Machine
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1428 Accepted Submission(s): 298
ACM. But a new problem comes, how to place the new machine into ACM?
ACM is a rectangular factor and can be divided into W * H cells. There are N retangular old machines in ACM and the new machine can not occupy any cell where there is old machines. The new machine needs M consecutive cells. Consecutive cells means some adjacent
cells in a line. You are asked to calculate the number of ways to choose the place for the new machine.
of the new machine. Then N lines follow, each of which contains 4 integers Xi1, Yi1, Xi2 and Yi2 (1 ≤ Xi1 ≤ Xi2 ≤ W, 1 ≤ Yi1 ≤ Yi2 ≤ H), indicating the coordinates of the
i-th old machine. It is guarantees that no cell is occupied by two old machines.
3 3 1 2
2 2 2 2
3 3 1 3
2 2 2 2
2 3 2 2
1 1 1 1
2 3 2 3
Sample Output
8
4
3
/*
hdu 4052 线段树扫描线、奇特处理 给你W*H大小的矩形,其中有N个地区不能使用(给出了这个地区的两个顶点的坐标即(x1,y1)
和(x2,y2)),问能下多少个1*M的矩形。 但是看见题目有想到了扫描线,但是一直不知道应该怎么处理后来偶然看见别人提示可以转换
成求面积,大致就有了思路 假设1*n的矩阵中放入1*m的矩阵,能有多少种? n-m+1
我们扫描每一列,两个相邻为n的旧机器中就能放下n-m+1个新机器,于是原先的旧机器矩形
就变成了(x1,y1,x2+ma-1,y2)(从下往上扫描)
(x1,y1,x2,y2+ma-1)(从左往右扫描)
而剩下的为被占据的位置就是方案数了
因为我是在每个旧机器往右边添加的,所以还要解决这一列没有从1开始的情况,所以在最左边
加上(1,1,ma,h+1)的矩阵
而且ma=1时,横着放和竖着放是一样的,所以除以2 但是第一个版本写出来一直 RuntimeError
后来实在没法又换了个,把离散化用vec处理终于出现了WR(TAT)
主要是 ma == 1 情况,因为我会在1添加一个矩阵,但是当ma==1时这个矩阵也被建立了就导致
(1,1,1,h+1) 由于是按边建树l=x1,r=x2-1 -> r<l (- -!好气) //应该多测几次的 然后进行了特判第一个也过了 hhh-2016-03-30 22:26:25
*/ //Second
#include <iostream>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <functional>
#include <map>
#include <algorithm>
#include <queue>
#include <vector>
#define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
using namespace std; const int maxn = 1000005;
vector<int> vec;
int w,h;
int x[maxn],y[maxn],tx[maxn],ty[maxn];
map<int,int > mp;
int n,ma;
struct node
{
int l,r;
int sum;
ll len;
int mid()
{
return (l+r)>>1;
}
} tree[maxn<<2]; void push_up(int i)
{
if(tree[i].sum)
tree[i].len = vec[tree[i].r+1]-vec[tree[i].l];
else if(tree[i].l == tree[i].r)
tree[i].len = 0;
else
tree[i].len = tree[lson].len+tree[rson].len;
} void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].sum = tree[i].len = 0;
if(l == r)
return;
build(lson,l,tree[i].mid());
build(rson,tree[i].mid()+1,r);
push_up(i);
} void push_down(int i)
{ } void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <= r)
{
tree[i].sum += val;
push_up(i);
return ;
}
int mid = tree[i].mid();
push_down(i);
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
push_up(i);
return ;
} struct edge
{
int l,r;
int high;
int va;
};
edge Line[maxn<<2];
int m;
bool cmp(edge a,edge b)
{
if(a.high != b.high)
return a.high < b.high;
else
return a.va > b.va;
} int tox;
ll ans;
void solve(int cur,int hi,int wi)
{
vec.clear();
if(cur)
{
for(int i =1; i <= n; i++)
swap(x[i],y[i]),swap(tx[i],ty[i]);
}
tox = 0;
for(int i = 1; i <= n; i++)
{
int t = min(wi+1,tx[i]+ma-1);
Line[tox].l = x[i],Line[tox].r =t,Line[tox].high = y[i],Line[tox++].va = 1;
Line[tox].l = x[i],Line[tox].r =t,Line[tox].high = ty[i],Line[tox++].va = -1;
vec.push_back(x[i]);
vec.push_back(t);
}
if(ma != 1)
{
Line[tox].l = 1,Line[tox].r = ma,Line[tox].high=1,Line[tox++].va=1;
Line[tox].l = 1,Line[tox].r = ma,Line[tox].high=hi+1,Line[tox++].va=-1;
vec.push_back(1),vec.push_back(ma);
}
sort(Line,Line+tox,cmp);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
int m = vec.size();
for(int i = 0; i < m; i++)
mp[vec[i]] = i;
build(1,0,m);
int l,r;
for(int i = 0; i < tox-1; i++)
{
l = mp[Line[i].l];
r = mp[Line[i].r]-1;
if(r < l)
continue;
Insert(1,l,r,Line[i].va);
ans -= (ll)tree[1].len*(Line[i+1].high-Line[i].high);
}
//cout << tans <<endl;
} int main()
{
while(scanf("%d%d%d%d",&w,&h,&n,&ma) != EOF)
{
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d%d",&x[i],&y[i],&tx[i],&ty[i]);
tx[i]++,ty[i]++;
} ans =(ll)w*h*2;
solve(0,h,w);
solve(1,w,h);
if(ma == 1)
ans /= 2;
printf("%I64d\n",ans);
}
return 0;
} /*
First: #include <iostream>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <functional>
#include <map>
#include <algorithm>
#include <queue> #define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
using namespace std; const int maxn = 1000005; ll w,h;
int n,ma;
int now;
struct node
{
int l,r;
int sum;
ll len;
int mid()
{
return (l+r)>>1;
}
} tree[maxn<<2];
ll hs[2][maxn]; void push_up(int i)
{
if(tree[i].sum)
tree[i].len = hs[now][tree[i].r+1]-hs[now][tree[i].l];
else if(tree[i].l == tree[i].r)
tree[i].len = 0;
else
tree[i].len = tree[lson].len+tree[rson].len;
} void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].sum = tree[i].len = 0;
if(l == r)
return;
build(lson,l,tree[i].mid());
build(rson,tree[i].mid()+1,r);
push_up(i);
} void push_down(int i)
{ } void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <= r)
{
tree[i].sum += val;
push_up(i);
return ;
}
int mid = tree[i].mid();
push_down(i);
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
push_up(i);
return ;
} struct edge
{
ll l,r;
ll high;
int va;
};
edge tx[maxn<<2];
edge ty[maxn<<2];
int m;
bool cmp(edge a,edge b)
{
if(a.high != b.high)
return a.high < b.high;
else
return a.va > b.va;
}
int bin(int cur,ll x)
{
int l = 0,r = m-1;
while(l <= r)
{
int mid = (l+r)>>1;
if(hs[cur][mid] == x)
return mid;
else if(hs[cur][mid] < x)
l = mid+1;
else
r = mid-1;
}
}
int tox,toy;
ll solve(int cur)
{
now = cur;
int len = (cur == 0 ? tox:toy);
m = 1;
for(int i = 1; i < len; i++) //ШЅжи
{
if(hs[cur][i] != hs[cur][i-1])
hs[cur][m++] = hs[cur][i];
}
// for(int i = 0;i < m;i++)
// printf("%d ",hs[cur][i]);
// cout <<endl;
build(1,0,m);
ll tans = 0;
int l,r;
for(int i = 0; i < len-1; i++)
{
if(cur == 0)
{
l = bin(cur,tx[i].l);
r = bin(cur,tx[i].r)-1;
Insert(1,l,r,tx[i].va);
tans += (ll)tree[1].len*(tx[i+1].high-tx[i].high);
}
else
{
l = bin(cur,ty[i].l);
r = bin(cur,ty[i].r)-1;
if(r < l )continue;
Insert(1,l,r,ty[i].va);
tans += (ll)tree[1].len*(ty[i+1].high-ty[i].high);
} //cout << tree[i].len << endl;
//cout << tans <<endl; }
//cout << tans <<endl;
return tans;
} int main()
{
while(scanf("%I64d%I64d%d%d",&w,&h,&n,&ma) != EOF)
{
tox = 0,toy = 0;
ll x1,y1,x2,y2;
for(int i = 1; i <= n; i++)
{
scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);
x2++,y2++;
ll t1 = (x2+ma-1)>w+1? w+1:x2+ma-1;
tx[tox].l = x1,tx[tox].r = t1,tx[tox].high = y1,tx[tox].va = 1;
hs[0][tox++] = x1;
tx[tox].l = x1,tx[tox].r = t1,tx[tox].high = y2,tx[tox].va = -1;
hs[0][tox++] = t1; t1 = (y2+ma-1)>h+1? h+1:y2+ma-1;
ty[toy].l = y1,ty[toy].r = t1,ty[toy].high = x1,ty[toy].va = 1;
hs[1][toy++] = y1;
ty[toy].l = y1,ty[toy].r = t1,ty[toy].high = x2,ty[toy].va = -1;
hs[1][toy++] = t1;
}
if(ma != 1){
tx[tox].l = 1,tx[tox].r = ma,ty[toy].l=1,ty[toy].r = ma;
tx[tox].high=1,tx[tox].va=1,ty[toy].high=1,ty[toy].va=1;
hs[0][tox++] = 1,hs[1][toy++]=1; tx[tox].l = 1,tx[tox].r = ma,ty[toy].l=1,ty[toy].r = ma;
tx[tox].high=h+1,tx[tox].va=-1,ty[toy].high=w+1,ty[toy].va=-1;
hs[0][tox++] = ma,hs[1][toy++] = ma;
}
sort(hs[0],hs[0]+tox);
sort(hs[1],hs[1]+toy);
sort(tx,tx+tox,cmp);
sort(ty,ty+toy,cmp);
ll ans = w*h*2; ans -= solve(0);
//printf("%I64d\n",ans);
ans -= solve(1);
if(ma == 1)
ans /= 2;
printf("%I64d\n",ans);
}
return 0;
} */
hdu 4052 线段树扫描线、奇特处理的更多相关文章
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu 5091(线段树+扫描线)
上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...
- HDU 5107 线段树扫描线
给出N个点(x,y).每一个点有一个高度h 给出M次询问.问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对全部的点和询 ...
- hdu 1255(线段树 扫描线) 覆盖的面积
http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所 ...
- HDU 5091 线段树扫描线
给出N个点.和一个w*h的矩形 给出N个点的坐标,求该矩形最多能够覆盖多少个点 对每一个点point(x.y)右边生成相应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍.遇到点则用 ...
- hdu 1542 线段树+扫描线 学习
学习扫描线ing... 玄学的东西... 扫描线其实就是用一条假想的线去扫描一堆矩形,借以求出他们的面积或周长(这一篇是面积,下一篇是周长) 扫描线求面积的主要思想就是对一个二维的矩形的某一维上建立一 ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
- hdu 3265 线段树扫描线(拆分矩形)
题意: 给你n个矩形,每个矩形上都有一个矩形的空洞,所有的矩形都是平行于x,y轴的,最后问所有矩形的覆盖面积是多少. 思路: 是典型的矩形覆盖问题,只不过每个矩形上多了一个矩 ...
- HDU 1828 线段树+扫描线(计算矩形周长并)
题意:给你n个矩形,然后矩形有可能重叠,要你求周长 思路:首先碰到这种矩形在数轴上那么第一反应应该想到的是扫描线, 做周长我们有两种方法 第一种,我们可以分开两部分求,第一遍求x轴上的贡献,第二遍求y ...
随机推荐
- Struts2之配置
Struts2的默认配置文件是struts.xml放在/web-inf/classes目录下,struts配置文件的最大作用就是配置Action与请求之间的对应关系,并配置逻辑视图名和物理视图名之间的 ...
- bzoj 4373 算术天才⑨与等差数列
4373: 算术天才⑨与等差数列 Time Limit: 10 Sec Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.ph ...
- codevs 3981 动态最大子段和
3981 动态最大子段和 http://codevs.cn/problem/3981/ 题目等级 : 钻石 Diamond 题目描述 Description 题目还是简单一点好... 有n个 ...
- JAVA线程池原理详解(1)
线程池的优点 1.线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用. 2.可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃. 线 ...
- 13-TypeScript单例模式
在JavaScript中,要实现设计模式比较复杂.而在TypeScript中因为使用面向对象的思想编程,要实现设计模式的方式与后端语言C#.Java等非常类似. 单例模式是一种常用的设计模式,通常用于 ...
- PHP模式设计之单例模式、工厂模式、注册树模式、适配器模式、观察者模式
php模式设计之单例模式 什么是单例模式? 单例模式是指在整个应用中只有一个实例对象的设计模式 为什么要用单例模式? php经常要链接数据库,如果在一个项目中频繁建立连接数据库,会造成服务器资源的很大 ...
- Nagios监控的部署与配置
[安装Nagios] yum install -y httpd httpd-devel httpd-tools mysql mysql-devel mysql-server php php-devel ...
- python 单例模式的四种创建方式
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- IDE-Android Studio 导入Ecplise项目不改变结构
Android Studio 导入 Ecplise创建的android 项目 无导入 不修改目录结构 首先,Ecplise 原有目录结构创建的android项目一枚 Sept 1 . 打开项目 S ...
- [52ABP实战课程系列]Docker&Ubuntu从入门到实战开课啦~
任何的课程都逃不开理论的支持 久等了各位,在Asp.NET Core2.0 项目实战入门视频课程结束后,根据发起的投票信息.Docker 排在首位.按照结果,我们开始进行Docker视频课程的录制. ...