第一次听到离散化是今年省赛的时候,一道矩形并的题,很水,就两个矩形...

今天再去做线段树已经发现离散化忘得差不多了...水逼的悲哀啊...

先看简单点的hdu 1698

http://acm.hdu.edu.cn/showproblem.php?pid=1698

先做这个水题,在做poj 2528,当然poj 2528也很水

一、建树

把hook作为线段建树,近乎直接套线段树的模板。

二、计算结果

void cal(int i)
{if(node[i].v){tot+=(node[i].r-node[i].l+1)*node[i].v;}else{cal(i*2);cal(i*2+1);}
}
//poj 2528算的时候也是这样,近乎模板啊
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define N 100005struct Node{int l,r,m,v;
};Node node[N*3];
int tot;void build(int i,int left,int right)
{Node &tmp=node[i];tmp.l=left;tmp.r=right;tmp.m=(left+right)>>1;tmp.v=1;if(left<right){build(i*2,left,tmp.m);build(i*2+1,tmp.m+1,right);}
}void update(int i,int left,int right,int v)
{Node &tmp=node[i];if(tmp.l==left&&tmp.r==right){tmp.v=v;return ;}if(tmp.v==v)return ;/*有这一句可以省一些时间*/if(node[i].v>0){node[i*2].v=node[i*2+1].v=node[i].v;/*存储父亲节点的值*/node[i].v=0;}/*downside >= or <=  think about m,m+1*/if(right<=tmp.m)update(i*2,left,right,v);elseif(tmp.m<left)update(i*2+1,left,right,v);else{update(i*2,left,tmp.m,v);update(i*2+1,tmp.m+1,right,v);}}
void cal(int i)
{if(node[i].v){tot+=(node[i].r-node[i].l+1)*node[i].v;}else{cal(i*2);cal(i*2+1);}
}int main()
{int ncase,k,n,q,i,l,r,v;//freopen("hdu 1698.in","r",stdin);scanf("%d",&ncase);for(k=1;k<=ncase;k++){scanf("%d%d",&n,&q);build(1,1,n);for(i=0;i<q;i++){scanf("%d%d%d",&l,&r,&v);update(1,l,r,v);}tot=0;cal(1);printf("Case %d: The total value of the hook is %d.\n",k,tot);}return 0;
}

再看poj 2528

谈谈离散化,举个例子,1-5,3-9,11-18三条线段,此题根本不需要线段长度,

所以直接当成

1->1

3->2;

5->3;

9->4;

11->5

18->6;

于是原来的线段就转化为 1->3,2->4,5->6.这样建树会节省空间

另外建树的时候有个问题,tree[N*3]会RE,要tree[N*4]

其他跟poj 2528 一样的,关于离散化的具体做法,我在注释里写清楚吧,下面贴代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define N 20002struct node{int l,r,c;
};
node tree[N*4];struct line{int s,id;
};line seg[N];int des[N][2],ans,numc[N];bool cmp(line a,line b)
{return a.s<b.s;
}void build(int i,int left,int right)
{tree[i].l=left;tree[i].r=right;tree[i].c=0;if(left!=right){int mid=(left+right)>>1;build(i*2,left,mid);build(i*2+1,mid+1,right);}
}void update(int i,int ll,int rr,int col)
{if(tree[i].l==ll&&tree[i].r==rr){tree[i].c=col;return;}if(tree[i].c==col)return;int mid=(tree[i].l+tree[i].r)>>1;if(tree[i].c>0){tree[i*2].c=tree[i*2+1].c=tree[i].c;tree[i].c=0;}if(rr<=mid)update(i*2,ll,rr,col);elseif(mid<ll)update(i*2+1,ll,rr,col);else{update(i*2,ll,mid,col);update(i*2+1,mid+1,rr,col);}
}void cal(int i)
{if(tree[i].c>0){if(!numc[tree[i].c]){numc[tree[i].c]=1;ans++;}}else{cal(i*2);cal(i*2+1);}
}int main()
{//freopen("in.txt","r",stdin);int i,j,ncase,n;scanf("%d",&ncase);while(ncase--){scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d",&des[i][0],&des[i][1]);seg[i*2].s=des[i][0];seg[i*2].id=-(i+1);seg[i*2+1].s=des[i][1];seg[i*2+1].id=i+1;/*这里解释一下,为什么是seg[i*2],seg[i*2+1]?des数组起到两个作用:一是记录原来的线段区间,就是这里的 scanf("%d%d",&des[i][0],&des[i][1]);二是记录转化后的线段区间,就是下面num记点的个数*/}sort(seg,seg+n*2,cmp);/*以下为离散化*/int tmp=seg[0].s,num=1;for(i=0;i<n*2;i++){if(seg[i].s!=tmp){num++;tmp=seg[i].s;}if(seg[i].id<0)des[-seg[i].id-1][0]=num;elsedes[seg[i].id-1][1]=num;}/*建树及更新*/build(1,1,num);int color=1;for(i=0;i<n;i++)update(1,des[i][0],des[i][1],color++);ans=0;memset(numc,0,sizeof(numc));cal(1);printf("%d\n",ans);}return 0;
}


												

poj 2528 离散化+线段树 hdu 1698 线段树 线段树题目类型一:染色计数 外加离散化相关推荐

  1. 线段树——HDU - 1698

    题目含义 就是初始化一堆数为1 可以经过操作把一个区间的数都改变 并求这堆数的总大小 题目分析 有一个 #include<iostream> #include<stdio.h> ...

  2. 线段树区间染色 浮水法 学习小记 Poj 2777 + Poj 2528

    复习过的东西必须时常拿来练练,虽说都是水题.... Poj 2777 典型的区间染色问题,貌似我的写法为了不数组越界必须多开一倍的数组空间.....还没有想到解决方法,有机会参考一下别人的写法. Po ...

  3. poj 2528 Mayor's posters(线段树+离散化)

    1 /* 2 poj 2528 Mayor's posters 3 线段树 + 离散化 4 5 离散化的理解: 6 给你一系列的正整数, 例如 1, 4 , 100, 1000000000, 如果利用 ...

  4. poj 2528 线段树离散化+染色

    题目链接 Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 92628 Accepted: 2645 ...

  5. POJ 2528 Mayor's posters (离散化和线段树使用)

    还是做了线段树的题目,玩了两天也要继续看看题目了.之前就有看离散化的概念,大家可以去百度百科一下,简单转载一个例子 离散化 的大概思路 : 比如说给你一组 数据 1 4 1000 100000, 如果 ...

  6. POJ - 2528 Mayor's posters (浮水法+线段树/离散化+线段树)

    题目链接 题意: n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000) .求出最后还能看见多少张海报. 分析1 离散 ...

  7. POJ 2528 Mayor's posters(线段树)

    题目大意 贴海报.每张海报的高度都是一样的,唯独宽度不一样.每张海报只能占用整数倍的单位线段长度,贴了 n(n<=10000) 张海报之后,有几张能够看见(有一个角能看见这张海报也算被看见了)? ...

  8. POJ - 2528 Mayor's posters(线段数+离散化)

    题目链接:点击查看 题目大意:给定一个长度为1e7的墙,然后给出n张海报,每张海报都会占据墙上的一部分宽度,问按照给出的次序往墙上贴海报, 最后有几张海报能露出来(露出部分也算) 题目分析:线段树的区 ...

  9. HDU - 6183 暴力,线段树动态开点,cdq分治

    B - Color itHDU - 6183 题目大意:有三种操作,0是清空所有点,1是给点(x,y)涂上颜色c,2是查询满足1<=a<=x,y1<=b<=y2的(a,b)点一 ...

最新文章

  1. python软件怎么用-如何使用Python编写一个桌面软件系统?步骤有哪些
  2. php中const和define,PHP中const和define的区别是什么
  3. Intellij IDEA调试
  4. data数值设置 vue_怎么改变vue中data的数据
  5. 原生js简单实现双向数据绑定原理
  6. 佐客牛排机器人餐厅_高大上!滕州这家餐厅竟然用机器人“跑堂”(图)
  7. 异构服务器的负载均衡及过载保护
  8. Oracle数据库案例整理-Oracle系统执行时故障-内存过少导致分配共享内存失败
  9. Ubuntu无法安装Xmind rpm包
  10. 大数据爬虫实习面试题
  11. Android Studio生成APP方法及其所在位置
  12. 子群的陪集-》群的拉格朗日定理
  13. 样条插值 spline interpolation matlab c++实现
  14. 【技术快报】9.26-10.2
  15. 博文收藏夹(updating)
  16. html怎么做出相框的效果,使用CSS3制作PS级的图片边框效果
  17. c语言数学函数库根号程序,C语言初学 数学中带根号的复杂计算问题
  18. 关于拉流端ts时间切片问题导致的直播黑屏问题
  19. Unity3D——主角面朝方向一定区域内对象角度计算
  20. 获取客户端mac地址 php,js获取客户端mac地址的方法

热门文章

  1. python快速排序法实现
  2. 0x80070057复制从服务器复制文件,Win10无法切换到本地帐户提示错误0x80070057怎么办?...
  3. webpack HMR
  4. 《Oracle视频教程》
  5. 爱情是什么? 婚姻是什么?
  6. 在c语言中为了结束while语序,2011级C语序设计基础教程课后习题答案.doc
  7. 关于计算机硬盘的详细分类及不同硬盘存储数据的方式
  8. 蓝桥云课linux入门3:用户及文件权限管理
  9. Kotlin的lateinit
  10. JAVA程序设计:近义词句子(LeetCode:5110)