poj 3109
| Time Limit: 5000MS | Memory Limit: 65536K | |
| Total Submissions: 2447 | Accepted: 678 | |
| Case Time Limit: 2000MS | ||
Description
There is an infinite square grid. Some vertices of the grid are black and other vertices are white.
A vertex V is called inner if it is both vertical-inner and horizontal-inner. A vertex V is called horizontal-inner if there are two such black vertices in the same row that V is located between them. A vertex V is called vertical-inner if there are two such black vertices in the same column that V is located between them.
On each step all white inner vertices became black while the other vertices preserve their colors. The process stops when all the inner vertices are black.
Write a program that calculates a number of black vertices after the process stops.
Input
The first line of the input file contains one integer number n (0 ≤ n ≤ 100 000) — number of black vertices at the beginning.
The following n lines contain two integer numbers each — the coordinates of different black vertices. The coordinates do not exceed 109 by their absolute values.
Output
Output the number of black vertices when the process stops. If the process does not stop, output -1.
Sample Input
4
0 2
2 0
-2 0
0 -2
Sample Output
5
Hint

题意:无限大的棋盘上有黑白两种棋,前后左右都被黑棋包围的白棋都会最终变为黑棋,求最后有多少黑棋。
思路:因为棋盘是无限大的,所以要进行离散化,将有用的坐标节点取出来重新排列,譬如考虑横坐标的离散化,把所有黑子的横坐标取出,去掉重复,按原来的位置先后排序后再把横坐标赋予新的
值,即该横坐标从左到右排列排在第几位,以1开头;纵坐标也可以同理进行离散化。
离散化后所有被黑子包住的白子都将会变成黑子。此时的任务就是数出被包围的白子的个数。可以对离散化后的图形进行一行一行的扫描,白子的个数可以用树状数组进行存储,对于每一行的取出来的每一个黑子的
横坐标,先判断该横坐标在前面的行中有没有被取出过,如果取出过,那么这次取出意味着有上下两个黑子,之间也许夹着白子,那么可以通过树状数组把存储在该横坐标中的白子个数提取出来。树状数组在关于这个横坐标上
白子个数的记录清零,方便下一次记录新情况。之后从这个黑子的横坐标开始直到下一个黑子的横坐标为止,找出两者的坐标差(不含这两个横坐标本身),这个坐标差就是两个黑子之间白子的个数,之后就可以对中间这个
区间中的每一个横坐标在树状数组中对应位置处加1,表示这些横坐标上出现过一个白子并记录之。遍历所有行的所有黑子即可得到最终答案。
AC代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N_MAX = +;
int N;
int X[N_MAX], Y[N_MAX];
vector<int>line[N_MAX];//一行一行的记录
bool visited[N_MAX];
ll bit0[N_MAX], bit1[N_MAX]; ll sum(ll *b,int i) {
ll s = ;
while (i>) {
s += b[i];
i -= i&-i;
}
return s;
} void add(ll *b,int i,ll x) {
while (i <= N_MAX) {
b[i] += x;
i += i&-i;
}
} ll sum(int to) {
return sum(bit1, to)*to + sum(bit0, to);
} ll sum(ll*b,int from,int to) {//计算区间(from,to]的和
return sum( to) - sum( from);
} void add(int from,int to,ll x) {//对[from,to]区间同时加上值x
add(bit0,from,-x*(from-));
add(bit1,from,x);
add(bit0,to+,x*to);//!!
add(bit1,to+,-x);
} int compress(int *x) {//离散化,每一个x坐标的含义新定义为:所有的x坐标中排第几,1为下标起点
vector<int>v(N);//千万别忘记初始化,使用distance
for (int i = ; i < N;i++) {
v[i] = x[i];
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for (int i = ; i < N;i++) {//!!!!!!!1
x[i] = distance(v.begin(), lower_bound(v.begin(), v.end(), x[i])) + ;
}
return v.size();
} int main() {
scanf("%d",&N);
for (int i = ; i < N;i++) {
scanf("%d%d",&X[i],&Y[i]);
}
int h = compress(Y);
int w = compress(X);
for (int i = ; i < N; i++) {//离散化后,把坐标存起来,之后即可一行一行的考虑
line[Y[i]].push_back(X[i]);
}
ll res = N;//res记录最终的黑点数
for (int i = ; i <= h;i++) {//!!!!
vector<int>&xs = line[i];//对于每一行,查找黑点之间的白点个数
sort(xs.begin(),xs.end()); //!!!!!!!!!!!!!!!
for (vector<int>::iterator it = xs.begin(); it != xs.end();it++) {
int x = *it;
ll s = sum(bit0, x - , x);//首先判断有没有以该值作为横坐标的白点,记录个数
if (visited[x]) {//如果这个横坐标以前到达过,再次到达就会封闭包围白点
res += s;
}
else
visited[x] = true;
add(bit0,x,-s);//在该横坐标处减去已经做记录的白点,清零,方便下次继续记录
//接下来计算从该黑点开始一直到下一个黑点为止中间的白点的个数
if ((it + ) != xs.end()) {
if(x+<*(it+)-){//中间多于1个白点
add(x + , *(it + )-, );
}
else if (x + == *(it + ) - ) {
add(bit0, x + , );//中间只有一个黑点
}
}
}
}
printf("%lld\n",res);
return ;
}
poj 3109的更多相关文章
- POJ - 3109 Inner Vertices
不存在-1的情况,而且最多一轮就结束了.如果新增加的黑点v0会产生新的黑点v1,那么v0和v1肯定是在一条轴上的,而原来这条轴上已经有黑点了. 离散以后扫描线统计,往线段上插点,然后查询区间上点数. ...
- poj很好很有层次感(转)
OJ上的一些水题(可用来练手和增加自信) (POJ 3299,POJ 2159,POJ 2739,POJ 1083,POJ 2262,POJ 1503,POJ 3006,POJ 2255,POJ 30 ...
- POJ题目分类推荐 (很好很有层次感)
著名题单,最初来源不详.直接来源:http://blog.csdn.net/a1dark/article/details/11714009 OJ上的一些水题(可用来练手和增加自信) (POJ 3299 ...
- POJ 2109 Inner Vertices(扫描线+树状数组)
[题目链接] http://poj.org/problem?id=3109 [题目大意] 在一个棋盘上放满白子,现在把一些白子变成黑子, 如果一个白子上下左右都有黑子,就会变成黑子,问最终黑子个数 [ ...
- POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理
Halloween treats Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7644 Accepted: 2798 ...
- POJ 2356. Find a multiple 抽屉原理 / 鸽巢原理
Find a multiple Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7192 Accepted: 3138 ...
- POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22286 ...
- POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37427 Accepted: 16288 Descr ...
- POJ 3254. Corn Fields 状态压缩DP (入门级)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9806 Accepted: 5185 Descr ...
随机推荐
- 【转】如何在VC下检测当前存在的串口及串口热拔插
当我们在用VS进行串口编程时,在打开串口前,经常想知道当前PC上存在多少个串口,哪些串口可用?哪些串口已经打开了,最好是在一个Combo Box中列表系统当前所有可用的串口以供选择,然而如何获取系统当 ...
- 强制类型转换(int)、(int&)和(int*)的区别
我们先来看两行代码: float x=1.75,y=1.75; cout<<(int)x<<" "<<(int&)y<<en ...
- Golang ioutil读写文件测试
运用 ioutil.ReadFile .ioutil.WriteFile package main import ( "io/ioutil" "log" &qu ...
- 使用el-checkbox实现全选,点击失效没有反应
最近在公司接收到了一个需求,给收藏夹的书籍添加批量.全选删除实现思路:点击全选改变item的checked,改变item的checked,重新便利一下所有item的checked来改变全选的selec ...
- ccf 201712-3 Crontab(Python实现)
一.原题 问题描述 试题编号: 201712-3 试题名称: Crontab 时间限制: 10.0s 内存限制: 256.0MB 问题描述: 样例输入 3 201711170032 201711222 ...
- 9-11.Yii2.0框架控制器分配视图并传参xss攻击脚本视图的过滤
目录 一维数组传参 新建控制器: 新建view模板 二维数组传参 新建控制器: 新建view模板 视图非法字符的过滤 新建控制器: 新建view模板 一维数组传参 新建控制器: D:\xampp\ht ...
- pandas处理较大数据量级的方法 - chunk,hdf,pkl
前情提要: 工作原因需要处理一批约30G左右的CSV数据,数据量级不需要hadoop的使用,同时由于办公的本本内存较低的缘故,需要解读取数据时内存不足的原因. 操作流程: 方法与方式:首先是读取数据, ...
- python爬虫基础11-selenium大全5/8-动作链
Selenium笔记(5)动作链 本文集链接:https://www.jianshu.com/nb/25338984 简介 一般来说我们与页面的交互可以使用Webelement的方法来进行点击等操作. ...
- 中移物联网onenet入门学习笔记2:中移物联的通信格式
中移物联网硬件接入协议:LWM2M协议,EDP协议,MQTT协议,HTTP协议,TCP透传,MODBUS协议,JT/T808协议,RCMP协议 8种通信协议的区别在哪? 详细比较 EDP:OneNET ...
- BZOJ 5299: [Cqoi2018]解锁屏幕
状压DP #include<cstdio> using namespace std; const int mod=1e8+7; int F[1000005][25],dis[25][25] ...