Hihocoder 1079 离散化
离散化这里有很多种方式
利用结构体记录最初的索引在按位置排序再记录排名即为离散的位置再按索引排回来
或者用数组记录排序后直接对原位置二分直接去找离散应在的位置
或者对数组排序后直接map<pos,rank> 记录位置
线段树离散化染色统计最后剩余多少种颜色
这里离散化要注意细节
给出附加两组数据先:
3 20
1 10
1 4
6 10
3 20
2 3
1 2
3 4
两组答案应该都为3
但这里如果直接计算的话第一组会计算得2
1-4和6-10 这里用到了所有的离散后的数据1-2和3-4本来1-4和6-10中间还有4-6的部分是1-10这张的但1-2被改为2,3-4被改为3没有1了所以输出为2
要是1-4后还有节点5的话就不会了至少节点5是1
所以这里可以采用给每个位置后增加一个位置0.5用来连接原先的所有的两个位置,这样连续的位置被染色后这个0.5的位置也被染掉了,之后被其它的修改两边会仍然保留这个点的颜色
所以这里最终离散也只是离散到点本来的海报还是连续的,除非添加题目中不会有的小数数据作为中间点,不然就会漏掉原来连续染色(贴海报)的某段
当然也可以通过像小Hi大神这么想问题才是看出问题的本质以及对本质的运用
#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
#include <string>
#include <ctime>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
#define cl(a,b) memset(a,b,sizeof a);
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mod 1000000007
const int inf = ~0u >> 2;
const ll INF = (1LL << 62) - 1;
double eps = 1e-9;
const int N = 1e6+5;
const int M = 21;
int ans=0, cnt;
int n, m;
int c[N<<2];
int lan[N << 2];
int color[N << 2];
void down(int rt, int l, int r);
void up(int rt) {
if (c[rt << 1] > 0 && c[rt << 1 | 1] > 0)
{
if (c[rt << 1] == c[rt << 1 | 1])
c[rt] = c[rt << 1];
else
c[rt] = -1;
}
else {
c[rt] = -1;
}
}
void down(int rt,int l,int r) {
int m = (l + r) >> 1;
if (lan[rt]!=0) {
c[rt << 1] = c[rt];
c[rt << 1 | 1] = c[rt];
lan[rt << 1] = lan[rt];
lan[rt << 1 | 1] = lan[rt];
}
lan[rt] = 0;
}
void build(int l, int r, int rt) {
if (l == r) {
c[rt] = 0;
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
up(rt);
}
void update(int L,int R,int value,int l, int r, int rt) {
if (L<=l&&r<=R) {
c[rt] = value;
lan[rt] = 1;
return;
}
down(rt,l,r);
int m = (l + r) >> 1;
if (m >= L) {
update(L,R, value, lson);
}
if(m < R){
update(L,R, value, rson);
}
up(rt);
}
void query2(int L,int R,int l,int r,int rt) {
if (L <= l&&R >= r) {
if (c[rt] > 0) {
color[c[rt]]++;
return;
}
if (l == r)return;
}
down(rt, l, r);
int m = (l + r) >> 1;
if (m >= L) {
query2(L, R, lson);
}
if(m<R){
query2(L, R, rson);
}
return;
}
struct node {
int index;
double pos;
int rank;
}nd[N];
int cmp(node a, node b) {
return a.pos < b.pos;
}
int cmp2(node a, node b) {
return a.index < b.index;
}
int main(){
memset(c, -1, sizeof c);
memset(lan, 0, sizeof lan);
int tlen;
scanf("%d%d", &m,&tlen);
cnt = 0;
for(int i=0;i<m;i++){
int op, l, r, value;
scanf("%d%d", &l, &r);
nd[cnt].index = i*2;
nd[cnt].pos = l;
cnt++;
nd[cnt].index = i*2+1;
nd[cnt].pos = r;
cnt++;
}
sort(nd, nd+cnt, cmp);
int tcnt = cnt;
for (int i = 0; i < tcnt; i++) {
nd[cnt].index = 999999;
nd[cnt++].pos = nd[i].pos + 0.5;
}
sort(nd, nd + cnt, cmp);
int rk = 1;
nd[0].rank = rk;
for (int i = 1; i < cnt; i++) {
if (nd[i].pos > nd[i - 1].pos)
nd[i].rank = ++rk;
else
nd[i].rank = rk;
}
sort(nd, nd + cnt, cmp2);
build(0, rk, 1);
for (int i = 0; i < m; i++) {
update(nd[i * 2].rank, nd[i * 2 + 1].rank, i+1, 1, rk, 1);
}
query2(1, rk, 1, rk, 1);
for (int i = 1; i <= m; i++)
if (color[i] != 0)
ans++;
printf("%d\n", ans);
return 0;
}
在线段树的通常用法中,线段树的节点是有2种不同的意义的,一种是离散型的,比如在Hiho一下 第二十周中,一个节点虽然描述的是一个区间[3, 9],但是实际上这样一个区间是{3, 4, 5, 6, 7, 8, 9}这样的意义。而另一种就是连续型的,比如就在这一周的问题中,一个节点如果描述的是一个区间[3, 9],它就确确实实描述的是在数轴上从3这个标记到9这个标记的这一段。
那么有的小朋友可能就要问了,这两种不同的意义有什么区别呢?
在小Hi看来,其实只有这样的几个区别:1.叶子节点:在离散型中,叶子节点是[i, i],而连续性中是[i, i + 1];2.分解区间:在离散型中,一段区间是分解成为[l, m], [m + 1, r],而在连续型中,是分解成为[l, m], [m, r];3.其他所有类似的判定问题。
那么亲爱的小朋友们,你们懂了么?
这里注意到l=r-1之后就可以不处理了,不然不加条件或不另外加条件会无线循环的另外之前的m+1<=R也就是m<R这里因为连续了可以改为m<=R了
#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
#include <string>
#include <ctime>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
#define cl(a,b) memset(a,b,sizeof a);
#define ll long long
#define lson l,m,rt<<1
#define rson m,r,rt<<1|1
#define mod 1000000007
const int inf = ~0u >> 2;
const ll INF = (1LL << 62) - 1;
double eps = 1e-9;
const int N = 1e6+5;
const int M = 21;
int ans=0, cnt;
int n, m;
int c[N<<2];
int lan[N << 2];
int color[N << 2];
void down(int rt, int l, int r);
void up(int rt) {
if (c[rt << 1] > 0 && c[rt << 1 | 1] > 0)
{
if (c[rt << 1] == c[rt << 1 | 1])
c[rt] = c[rt << 1];
else
c[rt] = -1;
}
else {
c[rt] = -1;
}
}
void down(int rt,int l,int r) {
int m = (l + r) >> 1;
if (lan[rt]!=0) {
c[rt << 1] = c[rt];
c[rt << 1 | 1] = c[rt];
lan[rt << 1] = lan[rt];
lan[rt << 1 | 1] = lan[rt];
}
lan[rt] = 0;
}
void build(int l, int r, int rt) {
if (l == r-1) {
c[rt] = 0;
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
up(rt);
}
void update(int L,int R,int value,int l, int r, int rt) {
//if (r <= L||l>=R)return;
if (L<=l&&r<=R) {
c[rt] = value;
lan[rt] = 1;
return;
}
if (l == r - 1)return;
down(rt,l,r);
int m = (l + r) >> 1;
if (m >= L) {
update(L,R, value, lson);
}
if(m <= R){
update(L,R, value, rson);
}
up(rt);
}
void query2(int L,int R,int l,int r,int rt) {
//if (r <= L || l>=R)return;
if (L <= l&&R >= r) {
if (c[rt] > 0) {
color[c[rt]]++;
return;
}
}
if (l == r - 1)return;
down(rt, l, r);
int m = (l + r) >> 1;
if (m >= L) {
query2(L, R, lson);
}
if(m<=R){
query2(L, R, rson);
}
return;
}
struct node {
int index;
double pos;
int rank;
}nd[N];
int cmp(node a, node b) {
return a.pos < b.pos;
}
int cmp2(node a, node b) {
return a.index < b.index;
}
int a[N];
int b[N];
map<int, int> f;
int main(){
memset(c, -1, sizeof c);
memset(lan, 0, sizeof lan);
int tlen;
scanf("%d%d", &m,&tlen);
cnt = 0;
for(int i=0;i<m;i++){
int op, l, r, value;
scanf("%d%d", &l, &r);
nd[cnt].index = i*2;
nd[cnt].pos = l;
cnt++;
nd[cnt].index = i*2+1;
nd[cnt].pos = r;
cnt++;
}
sort(nd, nd+cnt, cmp);
int rk = 1;
nd[0].rank = rk;
for (int i = 1; i < cnt; i++) {
if (nd[i].pos > nd[i - 1].pos)
nd[i].rank = ++rk;
else
nd[i].rank = rk;
}
sort(nd, nd + cnt, cmp2);
build(0, rk, 1);
for (int i = 0; i < m; i++) {
update(nd[i * 2].rank, nd[i * 2 + 1].rank, i+1, 1, rk, 1);
}
query2(1, rk, 1, rk, 1);
for (int i = 1; i <= m; i++)
if (color[i] != 0)
ans++;
printf("%d\n", ans);
return 0;
}
Hihocoder 1079 离散化的更多相关文章
- hihoCoder - 1079 - 离散化 (线段树 + 离散化)
#1079 : 离散化 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho在回国之后,又一次过起了朝7晚5的学生生活.当然了.他们还是在一直学习着各种算法 ...
- hihoCoder #1079 : 离散化 (线段树,数据离散化)
题意:有一块宣传栏,高一定,给出长度,再给出多张海报的张贴位置,问还能见到几张海报(哪怕有一点被看到)?假设海报的高于宣传栏同高. 思路:问题转成“给出x轴上长为L的一条线段,再用n条线段进行覆盖上去 ...
- poj 2528 Mayor's posters 线段树+离散化 || hihocode #1079 离散化
Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the ...
- hihoCoder#1079(线段树+坐标离散化)
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学 ...
- hiho #1079 : 离散化
描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去,有些海报 ...
- hihoCoder:#1079(线段树+离散化)
题目大意:给n个区间,有的区间可能覆盖掉其他区间,问没有完全被其他区间覆盖的区间有几个?区间依次给出,如果有两个区间完全一样,则视为后面的覆盖前面的. 题目分析:区间可能很长,所以要将其离散化.但离散 ...
- HihoCoder 1590 : 紧张的会议室(区间最大+离散化)
时间限制:20000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi的公司最近员工增长迅速,同时大大小小的会议也越来越多:导致公司内的M间会议室非常紧张. 现在小Hi知道公司目前有N个 ...
- hihocoder-1079题解(线段树+离散化)
一.题目链接 http://hihocoder.com/problemset/problem/1079 二.题意 给定一个长度为L的区间,给你n个子区间,没一个区间涂成一种颜色,问最后这个区间内有几种 ...
- [HIHO1079]离散化(线段树、染色)
题目链接:http://hihocoder.com/problemset/problem/1079 MD坑爹,线段查询的时候左闭右开.插完挨个点找一遍扔set里,注意没染色的情况. #include ...
随机推荐
- IIS8的证书设置
首先,打开IIS的网站,找到“服务器证书” 然后根据需要创建证书 创建好后,如果某一个网站(注意是网站,不是应用程序集)需要使用https则, 在右侧“绑定”一项中添加新的https连接,并选择对应的 ...
- js实现找质因数
实现最一个整数的质因数的拆分,例如:90可以才分为2*3*3*5,具体代码如下: <script> var num = prompt('请输入一个整数:','90'); var regex ...
- android解析json
android2.3提供的json解析类 android的json解析部分都在包org.json下,主要有以下几个类: JSONObject:可以看作是一个json对象 JSONStringer:js ...
- vs 2015 连接不上tfs 错误代码:TF31002
在vs2015里面怎么也连接不上,把地址放到浏览器里可以打开,所以点击右边的 在visual studio 中打开,然后将源码映射到本地
- cetnos 7 ntp服务的安装与配置
首先需要搭建yum本地仓库 http://www.cnblogs.com/jw35/p/5967677.html #搭建yum仓库方法 yum install ntp -y #安装n ...
- Docking Windows Phone controls to the bottom of a StackPanel
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinit ...
- *HDU3486 RMQ+二分
Interviewe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- 为Office365增加密码过期自动提醒功能
最近有人和我反应,无法查看所有员工的Office365的密码过期时间.最好可以批量查看,如果能在过期前几天发个提醒邮件就更好了. $pw = ConvertTo-SecureString 'your_ ...
- Windows 7 常用快捷键
常用的快捷键 Win键+D 回到桌面/当前界面(切换)Win键+M 回到桌面Win键+E 资源管理器Win键+R 运行 Win键+U 控制面板->所有控制面板项->轻松访问中心 Win键+ ...
- 不断优化,重构我的代码-----拖拽jquery插件
最近学东西学的有点太散了,歇一阵子,重新完善之前的JQ插件,今天先上拖拽吧 // JavaScript Document (function($){ var defaults = { actionEl ...