离散化这里有很多种方式

利用结构体记录最初的索引在按位置排序再记录排名即为离散的位置再按索引排回来

或者用数组记录排序后直接对原位置二分直接去找离散应在的位置

或者对数组排序后直接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 离散化的更多相关文章

  1. hihoCoder - 1079 - 离散化 (线段树 + 离散化)

    #1079 : 离散化 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho在回国之后,又一次过起了朝7晚5的学生生活.当然了.他们还是在一直学习着各种算法 ...

  2. hihoCoder #1079 : 离散化 (线段树,数据离散化)

    题意:有一块宣传栏,高一定,给出长度,再给出多张海报的张贴位置,问还能见到几张海报(哪怕有一点被看到)?假设海报的高于宣传栏同高. 思路:问题转成“给出x轴上长为L的一条线段,再用n条线段进行覆盖上去 ...

  3. poj 2528 Mayor's posters 线段树+离散化 || hihocode #1079 离散化

    Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the ...

  4. hihoCoder#1079(线段树+坐标离散化)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学 ...

  5. hiho #1079 : 离散化

    描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去,有些海报 ...

  6. hihoCoder:#1079(线段树+离散化)

    题目大意:给n个区间,有的区间可能覆盖掉其他区间,问没有完全被其他区间覆盖的区间有几个?区间依次给出,如果有两个区间完全一样,则视为后面的覆盖前面的. 题目分析:区间可能很长,所以要将其离散化.但离散 ...

  7. HihoCoder 1590 : 紧张的会议室(区间最大+离散化)

    时间限制:20000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi的公司最近员工增长迅速,同时大大小小的会议也越来越多:导致公司内的M间会议室非常紧张. 现在小Hi知道公司目前有N个 ...

  8. hihocoder-1079题解(线段树+离散化)

    一.题目链接 http://hihocoder.com/problemset/problem/1079 二.题意 给定一个长度为L的区间,给你n个子区间,没一个区间涂成一种颜色,问最后这个区间内有几种 ...

  9. [HIHO1079]离散化(线段树、染色)

    题目链接:http://hihocoder.com/problemset/problem/1079 MD坑爹,线段查询的时候左闭右开.插完挨个点找一遍扔set里,注意没染色的情况. #include ...

随机推荐

  1. 【算法杂谈】LJX的迪杰斯特拉算法报告

    迪杰斯特拉(di jie qi)算法 这里有一张图: 假设要求从1号节点到5号节点的最短路.那么根据迪杰斯特拉算法的思想,我们先看: 节点1,从节点1出发的一共有3条路,分别是1-6.1-3.1-2. ...

  2. SpringMVC注解@RequestParam全面解析---打酱油的日子

    在SpringMVC后台控制层获取参数的方式主要有两种,一种是request.getParameter("name"),另外一种是用注解@RequestParam直接获取.这里主要 ...

  3. Python for Informatics 第11章 正则表达式四(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.3 组合查询和抽取 如果我 ...

  4. 使用BigDecimal进行精确运算以及格式化输出数字

    一.引言    借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供 ...

  5. Learn ZYNQ (8)

    在zed的PS端运行spark(已成功): (1)设置uboot为sd卡启动rootfs: "sdboot=if mmcinfo; then " \                 ...

  6. Xamarin.iOS Unified API 注意要点

    新数据类型 NATIVE TYPE 32-BIT BACKING TYPE 64-BIT BACKING TYPE System.nint System.Int32 (int) System.Int6 ...

  7. server与Portal联合,portal许可过期无法登录。

    server与Portal联合,portal许可过期无法登录,怎样解除联合. 解决方案由峥姐友情提供~~ (1)删除有两种方式(①/②选其一即可): ①类似 链接ttps://sunl.esrichi ...

  8. Unite洛杉矶峰会精彩回顾:从图形、平台再到VR

    产品质量与工作流程 在Unity的研发过程中,保持创新的步伐与稳定性的平衡一直是一个挑战.Unity曾经向所有的用户承诺:Unity将专注于提升产品的质量并保证Unity版本稳定性的决心. 大会伊始, ...

  9. Spring的JDBC框架

    转自: http://www.cnblogs.com/windlaughing/p/3287750.html Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发. Spring主要 ...

  10. Altium Designer 生成Gerber文件