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 输出 一个数,表 ...
随机推荐
- Tensorflow CPU mask-rcnn 训练模型
基于cpu版的tensorflow ,使用mask_rcnn训练识别箱子的模型 代码参考(https://blog.csdn.net/disiwei1012/article/details/79928 ...
- Linux cmus
一.简介 CMus 是一款类似于MOC, Herrie 或 mp3blaster 的基于终端的音乐播放器,支持 Ogg Vorbis, FLAC, MP3, WAV, Musepack, WavPac ...
- Yii2验证登录得User类
Yii2中的 Class yii\web\User 是如果进行验证登录,如果我们使用User类验证登录会给我们减少很多麻烦.在此就拿Yii2中自带的登录功能进行说明. 配置.在应用配置文件compo ...
- SQLAlchemy 进阶
SQLAlchemy使用 1.执行原生SQL语句 from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engin ...
- linux信号基本概念及如何产生信号
linux信号基本概念及如何产生信号 摘自:https://blog.csdn.net/summy_j/article/details/73199069 2017年06月14日 09:34:21 阅读 ...
- VS code docker 调试 asp.net core
前言 .net core的诞生就是为了解决跨平台的事情的,所以.net core app运行在linux.macOS.docker上也不是什么新鲜事了. 相信已经有不少.net core的项目已经部署 ...
- Ubuntu下成功安装台式机网卡realtek的rtl8188eu芯片驱动并实现AP功能
1,下载驱动 https://github.com/lwfinger/rtl8188eu 使用注意: https://github.com/lwfinger/rtl8188eu/issues/3 2. ...
- 20169219 实验一 Java开发环境的熟悉(Linux + IDEA)
实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA 编辑.编译.运行.调试Java程序. 如条件断点设置:我们在第14行左边断点处单击鼠标右键,弹出断点属性框,我们设置条件&qu ...
- SQL Server乱码处理(ASCII)
CREATE FUNCTION [dbo].[RegexReplace] ( @string VARCHAR(MAX), --被替换的字符串 @pattern VARCHAR(255), --替换模板 ...
- tomcat访问日志关闭
在tomcat(实例)路径下[conf/server.xml]中修改,以下节点(注释掉该节点): tomcat catalina.out日志关闭 在tomcat(主目录)路径下[bin/catalin ...