题目传送门

  题意:给出很多黑点,当一个坐标上下左右都有黑点时,这个点也被染成黑色,问最后黑点的数量。

  思路:首先,一个很显然的结论,不可能出现无限染色的情况。所以不会输出-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

无限大正方形网格里有n个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点)。每秒钟,所有内部白点同时变黑,直到不存在内部白点为止。你的任务是统计最后网格中的黑点个数。 内部白点的定义:一个白色的整点P(x,y)是内部白点当且仅当P在水平线的左边和右边各至少有一个黑点(即存在x1 < x < x2使得(x1,y)和(x2,y)都是黑点),且在竖直线的上边和下边各至少有一个黑点(即存在y1 < y < y2使得(x,y1)和(x,y2)都是黑点)。

Input

输入第一行包含一个整数n,即初始黑点个数。以下n行每行包含两个整数(x,y),即一个黑点的坐标。没有两个黑点的坐标相同,坐标的绝对值均不超过109。

Output

输出仅一行,包含黑点的最终数目。如果变色过程永不终止,输出-1。

Sample Input

4
0 2
2 0
-2 0
0 -2

Sample Output

5

数据范围
36%的数据满足:n < = 500
64%的数据满足:n < = 30000
100%的数据满足:n < = 100000

bzoj1818 内部白点(好题) 离散化+树状数组的更多相关文章

  1. HDU 6318.Swaps and Inversions-求逆序对-线段树 or 归并排序 or 离散化+树状数组 (2018 Multi-University Training Contest 2 1010)

    6318.Swaps and Inversions 这个题就是找逆序对,然后逆序对数*min(x,y)就可以了. 官方题解:注意到逆序对=交换相邻需要交换的次数,那么输出 逆序对个数 即可. 求逆序对 ...

  2. CodeForces 540E - Infinite Inversions(离散化+树状数组)

    花了近5个小时,改的乱七八糟,终于A了. 一个无限数列,1,2,3,4,...,n....,给n个数对<i,j>把数列的i,j两个元素做交换.求交换后数列的逆序对数. 很容易想到离散化+树 ...

  3. Ultra-QuickSort(归并排序+离散化树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 50517   Accepted: 18534 ...

  4. HDU 5862 Counting Intersections(离散化+树状数组)

    HDU 5862 Counting Intersections(离散化+树状数组) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 D ...

  5. BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组

    BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 ...

  6. poj-----Ultra-QuickSort(离散化+树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 38258   Accepted: 13784 ...

  7. Code Forces 652D Nested Segments(离散化+树状数组)

     Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  8. hdu 3015 Disharmony Trees (离散化+树状数组)

    Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  9. 【bzoj4627】[BeiJing2016]回转寿司 离散化+树状数组

    题目描述 给出一个长度为n的序列,求所有元素的和在[L,R]范围内的连续子序列的个数. 输入 第一行包含三个整数N,L和R,分别表示寿司盘数,满意度的下限和上限. 第二行包含N个整数Ai,表示小Z对寿 ...

  10. 【bzoj5055】膜法师 离散化+树状数组

    题目描述 给定一个序列$a$,求满足$i<j<k$且$a_i<a_j<a_k$的三元组$(i,j,k)$的个数. 输入 第一行1个数 n 第二行n个数 a_i 输出 一个数,表 ...

随机推荐

  1. Ionic01 简单介绍、环境搭建、创建项目、项目结构、创建组件、创建页面、子页面跳转

    1 Ionic 基本介绍 Ionic 是一款基于 Angular.Cordova 的强大的 HTML5 移动应用开发框架 , 可以快速创建一个跨平台的移动应用.可以快速开发移动 App.移动端 WEB ...

  2. IDEA maven打包时跳过测试

    配置这个install -Dmaven.test.skip=true, 可以跳过business项目本地启动自动跑测试用例

  3. Windows cmd 快捷操作

    复制当前文件夹下符合条件的文件名字到文件 dir /B *-gd.dll > debug /B是只显示文件名,不包含所在路径 复制当前文件夹下文件到另外的地方 xcopy /s/d *-gd.d ...

  4. 利用arcgis实现经纬度和平面坐标互转

    一平面直角坐标(投影坐标)转经纬度 基本程序是这样的 经纬度计算操作 1. 定义坐标系:在AreToolbox下→数据管理工具→投影和变换→定义投影→输入数据或要素点击▼选择定义同层(同时在坐标系中点 ...

  5. Django框架 之 querySet详解

    Django框架 之 querySet详解 浏览目录 可切片 可迭代 惰性查询 缓存机制 exists()与iterator()方法 QuerySet 可切片 使用Python 的切片语法来限制查询集 ...

  6. Part4_lesson4---Bootloader架构设计

    1.第一阶段程序设计 第二阶段程序设计

  7. mybatis使用count返回int的方法

    <select id="countByExample" resultType="java.lang.Integer" > select count( ...

  8. .net Reflection(反射)- 一

    Reflection 反射需要引用 using System.Reflection; 命名空间.  通过 Assembly 类的 Load( ); 加载指定的 程序集 Assembly 是不能被实例化 ...

  9. python 读取mysql存储的文件路径下载文件,内容解析,上传七牛云,内容入es

    #!/usr/bin/env python # -*- coding: utf-8 -*- import ConfigParser import json import os import re fr ...

  10. ubuntu 14.04 x64下安装libreoffice

    LibreOffice是ubuntu 上的办公软件很多人都知道微软公司的的Word.Excel.PowerPoint和Outlook,但是很少有人知道LibreOffice. LibreOffice靠 ...