bzoj1818 内部白点(好题) 离散化+树状数组
题意:给出很多黑点,当一个坐标上下左右都有黑点时,这个点也被染成黑色,问最后黑点的数量。
思路:首先,一个很显然的结论,不可能出现无限染色的情况。所以不会输出-1,当n为0或者1时,答案就是0或者1.
其次,每一个新增的点其实就是横线和竖线的交点,我们先把所有的坐标都离散化,然后把横线和竖线都处理出来,分三类,横线,竖线的下端点,竖线的上端点,按照y从小到大排序。遇到竖线下端点时,树状数组x的位子加一,遇到上端点,x的位置减一,遇到横线,则是一段区间求和。
比较重要的端点问题和处理这三类点(线)的优先级问题,显然应该先删去,再求和,最后加上,所以在结构体中加入一个flag,既表示种类又表示优先级。区间求和的时候端点要注意。
我一开始将一条线上的所有点全部合并在同一条直线上,比如(1,1),(1,2),(1,3)直接合并成(1,1)到(1,3),这样处理首先很麻烦,其次会遇到某两条直线把(1,2)这个点染成黑色,重复计算的问题,所以只需要老老实实的分成很多线段就可以了。
#include<bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=;
struct node{
ll x,y;
}a[maxn];
struct line{
ll x1,y1,x2,y2;
int flag;//1下端点 2横线 3代表上端点
}b[maxn<<];
bool cmpx(const node &u,const node &v)
{
if(u.x==v.x)return u.y<v.y;
return u.x<v.x;
}
bool cmpy(const node &u,const node &v)
{
if(u.y==v.y)return u.x<v.x;
return u.y<v.y;
}
bool cmpli(const line &u,const line &v){
if(u.y1==v.y1)return u.flag>v.flag;
return u.y1<v.y1;
}
ll hash1[maxn<<],hash2[maxn<<];
int n,h;
inline void Hash(){
sort(hash1+,hash1++h);
int m=;
for(int i=;i<=h;i++)
{
if(i==||hash1[i]!=hash1[i-]){
hash2[++m]=hash1[i];
}
}
for(int i=;i<=n;i++)
{
a[i].x=lower_bound(hash2+,hash2++m,a[i].x)-hash2;
a[i].y=lower_bound(hash2+,hash2++m,a[i].y)-hash2;
}
} ll c[maxn<<];
inline void add(int x,ll val)
{
while(x<=)
{
c[x]+=val;
x+=(x&(-x));
}
}
inline ll getsum(int x)
{
ll res=;
while(x>)
{
res+=c[x];
x-=(x&(-x));
}
return res;
}
int main(){
cin>>n;
for(int i=;i<=n;i++)
{
scanf("%lld%lld",&a[i].x,&a[i].y);
hash1[++h]=a[i].x,hash1[++h]=a[i].y;
}
if(n<=){
printf("%d\n",n);
return ;
}
Hash();
sort(a+,a++n,cmpx);
ll xx=a[].x,yy=a[].y;
int totline=;
for(int i=;i<=n;i++)//竖线
{
if(a[i].x==xx)
{
b[totline].x1=xx;
b[totline].y1=yy;
b[totline].x2=a[i].x;
b[totline].y2=a[i].y;
xx=a[i].x;
yy=a[i].y;
totline++;
}else{
xx=a[i].x;
yy=a[i].y; }
if(i==n){
totline--;
}
}
sort(a+,a++n,cmpy);
for(int i=;i<=totline;i++)
{
b[i].flag=;
b[i+totline]=b[i];
b[i+totline].flag=;
b[i].x2=b[i].x1,b[i].y2=b[i].y1;
b[i+totline].x1=b[i+totline ].x2,b[i+totline].y1=b[i+totline ].y2;
}
totline<<=;
totline++;
xx=a[].x,yy=a[].y;
for(int i=;i<=n;i++)//竖线
{
if(a[i].y==yy)
{
b[totline].x1=xx;
b[totline].y1=yy;
b[totline].x2=a[i].x;
b[totline].y2=a[i].y;
b[totline].flag=;
xx=a[i].x;
yy=a[i].y;
totline++;
}else{
xx=a[i].x;
yy=a[i].y;
}
if(i==n)totline--;
}
sort(b+,b++totline,cmpli);
//1下端点 2横线 3代表上端点
// for(int i=1;i<=totline;i++)
// {
// printf("i:%d flag:%d x1:%d y1:%d x2:%d y2:%d\n",i,b[i].flag,b[i].x1,b[i].y1,b[i].x2,b[i].y2);
// }
ll ans=; for(int i=;i<=totline;i++)
{ if(b[i].flag==){
add(b[i].x1,);
}else if(b[i].flag==){
xx=b[i].x1,yy=b[i].x2;
if(yy->=xx+){
ans-=getsum(xx);
ans+=getsum(yy-);
} }else if(b[i].flag==){
add(b[i].x1,-);
}
}
printf("%lld\n",ans+n);
} /* 10
6 7
3 8
5 2
6 4
1 5
5 4
1 10
8 7
1 8
4 10 9
2 4
4 1
8 4
7 1
7 10
1 10
6 4
6 8
6 1 */
1818: [Cqoi2010]内部白点
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1418 Solved: 635
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
0 2
2 0
-2 0
0 -2
Sample Output
数据范围
36%的数据满足:n < = 500
64%的数据满足:n < = 30000
100%的数据满足:n < = 100000
bzoj1818 内部白点(好题) 离散化+树状数组的更多相关文章
- HDU 6318.Swaps and Inversions-求逆序对-线段树 or 归并排序 or 离散化+树状数组 (2018 Multi-University Training Contest 2 1010)
6318.Swaps and Inversions 这个题就是找逆序对,然后逆序对数*min(x,y)就可以了. 官方题解:注意到逆序对=交换相邻需要交换的次数,那么输出 逆序对个数 即可. 求逆序对 ...
- CodeForces 540E - Infinite Inversions(离散化+树状数组)
花了近5个小时,改的乱七八糟,终于A了. 一个无限数列,1,2,3,4,...,n....,给n个数对<i,j>把数列的i,j两个元素做交换.求交换后数列的逆序对数. 很容易想到离散化+树 ...
- Ultra-QuickSort(归并排序+离散化树状数组)
Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 50517 Accepted: 18534 ...
- HDU 5862 Counting Intersections(离散化+树状数组)
HDU 5862 Counting Intersections(离散化+树状数组) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 D ...
- BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组
BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 ...
- poj-----Ultra-QuickSort(离散化+树状数组)
Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 38258 Accepted: 13784 ...
- Code Forces 652D Nested Segments(离散化+树状数组)
Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- hdu 3015 Disharmony Trees (离散化+树状数组)
Disharmony Trees Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 【bzoj4627】[BeiJing2016]回转寿司 离散化+树状数组
题目描述 给出一个长度为n的序列,求所有元素的和在[L,R]范围内的连续子序列的个数. 输入 第一行包含三个整数N,L和R,分别表示寿司盘数,满意度的下限和上限. 第二行包含N个整数Ai,表示小Z对寿 ...
- 【bzoj5055】膜法师 离散化+树状数组
题目描述 给定一个序列$a$,求满足$i<j<k$且$a_i<a_j<a_k$的三元组$(i,j,k)$的个数. 输入 第一行1个数 n 第二行n个数 a_i 输出 一个数,表 ...
随机推荐
- Junit问题01 利用 @Autowired 注入失效问题
1 利用 @Autowired 注入失效问题 1.1 问题描述 在使用Junit作为测试框架的单元测试中,直接了用@Autowired记性依赖注入时总是注入失败 1.2 问题原因 在测试类中没有设定上 ...
- 246. Strobogrammatic Number 上下对称的数字
[抄题]: A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at u ...
- Python学习笔记_Python向Excel写入数据
实验环境 1.OS:Win 10 64位 2.Python 3.7 3.如果没有安装xlwt库,则安装:pip install xlwt 下面是从网上找到的一段代码,网上这段代码,看首行注释行,是在L ...
- 基于.Net平台常用的组件和框架整理
转载自:http://www.cnblogs.com/hgmyz/p/5313983.html 基于转载进行补充 RPC框架: RPC:远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而 ...
- Python的split()函数
手册中关于split()用法如下: str.split(sep=None, maxsplit=-1) Return a list of the words in the string, usi ...
- URAL 1748. The Most Complex Number(反素数)
题目链接 题意 :给你一个n,让你找出小于等于n的数中因子个数最多的那个数,并且输出因子个数,如果有多个答案,输出数最小的那个 思路 : 官方题解 : (1)此题最容易想到的是穷举,但是肯定超时. ( ...
- Java变量的修饰符
1.public public的类.类属变量及方法,包内及包外的任何类均可以访问: 2.protect protected的类.类属变量及方法,包内的任何类,及包外的那些继承了此类的子类才能访问: 3 ...
- CreateExcel 导出Excel
public class CreateExcel { /// <summary> /// 用Excel组件导出Excel文件 /// </summary> /// <pa ...
- C# Socket通信改进记录
1. Socket 使用原始Socket,Send和Recv方法 进行发送和消息获取.(另起后台线程 不停获取和发送) public void RecvMsg() { //receive messag ...
- 利用Response.Buffer做类似异步效果
在page_load加入以下代码 Response.Buffer = false; //这句话非常重要 for (int i = 0; i < 10; i++) { Thread.Sleep( ...