线段树

题意:很明显的线段树。做了这题更加让我注意了用点和用段来建树的区别。这题是用点来表示线段的。一开始从0到10^9这个点之间的线段都是白色的,然后m个更新,每个更新 a,b,col,表示从点a到点b这条线段染成黑色或白色,问最后,白色线段中最长的是哪一段,输出它的位置(即线段两端的端点)

注意更新的时候a,b的数值范围是 0<a<b<10^9 , 其实这样给数据方便了处理,否则的话最后要搞一下挺烦的

先看看用段和用点表示线段树的区别。用点的话,0,1,表示的长度是1。1,3表示的长度是2。而用段的话1,3表示的长度是3,就是这个意思

线段树的建树,无论在何种情况下,应该说建树的原则都是二分长度,而和点或者段无关,但是由于点和段的区别要改变一下写法

如果是点

build(1,n,1);  //其实总区间的长度是n-1,表示用第1个点到第n个点之间的线段来建树

所以二分的时候是这样的

mid=(l+r)>>1;

build(l,mid,lch(rt));

build(mid,r,rch(rt));

//注意这里的mid表示的依然是点,这样写才是二分长度

如果是段

build(1,n,1); //这里的长度实际上是n,表示第1段到第n段的单位线段来建树

所以二分的时候应该是这样

build(l,mid,lch(rt));

build(mid+1,r,rch(rt));

//这里mid表示的依然是第几段,这样做才是二分长度

说完了该说这题到底怎么解了,解法没什么特别,典型的解法

1.首先离散化,否则数据太大了,而用到的很少

2.整段更新区间的信息,为了提高效率用LAZY思想,即每次更新不要一直深入到叶子

(LAZY思想,cnt=1,表示该区间整段为黑色,cnt=0表示整段区间为白色,cnt=-1表示区间不止一种颜色,不确定)

3.最后一个查询,查询的意义是查询整个区间中一共有多少个,查询的时候,遇到cnt=1直接返回,因为该区间全部为黑,不必记录也不必继续深入了,遇到cnt=0,记录这个区间,并且返回,不必继续深入。如果是cnt=-1,就继续深入。

把白色的区间都保存在一个表中,表中没个元素表示一段白色的左右端点,而且我们可以知道这个表的端点是连续的

即 c[1].l < c[i].r <= c[2].l < c[2].r <= c[3].l < c[3].r <= ……………………c[n].l < c[n].r

为什么呢?因为查询函数,其实就是遍历函数,我们的遍历顺序决定了我们能得到一个有序的表

注意上面的不等式中有一些等号吧,是等号的地方就是说这两个区间其实是连着的,可以并为一个区间(为什么它们一开始的时候没有在一起是因为遍历的时候把它们拆开了)

所以我们扫描一次这个表,把连着的白色区间并起来,知道不能为止就计算它的长度,并不断更新最大长度,那我们就可以得到长度最长的区间了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 1000000000
#define N 10010
#define M 5010
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:bstruct point{int m,f,n;
}p[N];
struct segment{int l,r,v;
}s[M];
struct tree{int l,r,cnt;int mid(){ return (l+r)>>1; }
}t[4*N];
int m,num;struct ran{int l,r;
}c[N];
int nc;int cmp(struct point a ,struct point b)
{return a.n<b.n;
}void build(int l ,int r ,int rt)
{t[rt].l=l; t[rt].r=r; t[rt].cnt=0;if(l+1==r) return ;int mid=t[rt].mid();build(l,mid,lch(rt));build(mid,r,rch(rt));
}void updata(int l ,int r ,int v ,int rt)
{if(t[rt].cnt == v) return ; //剪枝if(t[rt].l == l && t[rt].r == r){t[rt].cnt=v;return ;}if(t[rt].cnt!=-1) //当前节点是纯色的,传递给它的孩子并且记录其为不纯色的
    {t[lch(rt)].cnt=t[rch(rt)].cnt=t[rt].cnt;t[rt].cnt=-1;}int mid=t[rt].mid();if(r<=mid)updata(l,r,v,lch(rt));else if(l>=mid)updata(l,r,v,rch(rt));else{updata(l,mid,v,lch(rt));updata(mid,r,v,rch(rt));}
}void query(int rt)
{if(t[rt].cnt==1) //该区间全部是黑色的没必要再继续下去return ;if(t[rt].cnt==0) //该区间全部是白色的没必要继续下去,直接记录
    {c[nc].l=t[rt].l-1;c[nc].r=t[rt].r-1;nc++;return ;}if(t[rt].l+1==t[rt].r) return ;//剩下的情况就是为-1的情况无法确定的
    query(lch(rt));query(rch(rt));
}void solve()
{build(1,num,1);for(int i=0; i<m; i++)updata(s[i].l , s[i].r , s[i].v , 1);nc=0;query(1); //统计出所有白色的线段
//    for(int i=0; i<nc; i++) printf("[%d,%d]\n",c[i].l,c[i].r);int maxlen=-1;int len;int resl,resr;int l,r;l=c[0].l; r=c[0].r;for(int i=0; i<nc-1; i++){if(c[i+1].l == c[i].r) //可以继续合并一个区间r=c[i+1].r;else //第i+1个区间不能合并进来
        {len= p[r].n - p[l].n;if(len>maxlen){maxlen=len;resl=l;resr=r;}l=c[i+1].l;r=c[i+1].r;}}len= p[r].n - p[l].n;if(len>maxlen){ resl=l; resr=r; }printf("%d %d\n",p[resl].n , p[resr].n);
}int main()
{while(scanf("%d",&m)!=EOF){m++;s[0].v=0;p[0].f=0; p[0].m=0; p[0].n=0;p[1].f=1; p[1].m=0; p[1].n=MAX;int n=2;for(int i=1; i<m; i++){int l,r; char col[5];scanf("%d%d%s",&l,&r,col);s[i].v= (col[0]=='b')?1:0;p[n].m=i;   p[n].f=0;   p[n].n=l;p[n+1].m=i; p[n+1].f=1; p[n+1].n=r;n+=2;}sort(p,p+n,cmp);num=0;for(int i=0; i<n; i++){int mm=p[i].m;if(i==0 || p[i].n!=p[i-1].n) p[num++]=p[i];if(p[i].f) s[mm].r=num;else       s[mm].l=num;}
//        for(int i=0; i<num; i++) printf("%d ",p[i].n); printf("\n");
//        for(int i=0; i<m; i++) printf("[%d,%d] %d\n",s[i].l,s[i].r,s[i].v);
        solve();}return 0;
}

转载于:https://www.cnblogs.com/scau20110726/archive/2013/04/03/2998742.html

ural(Timus) 1019 Line Painting相关推荐

  1. 1019.Line Painting(线段树 离散化)

    1019 离散化都忘记怎么写了 注意两个端点 离散化后用线段树更新区间 混色为-1  黑为2  白为1  因为N不大 最后直接循环标记这一段的颜色查找 1 #include <iostream& ...

  2. Ural(Timus) 1146. Maximum Sum

    DP,最大子矩阵和:先按列压缩为一维i,在用最大连续子序列和来求.在枚举列压缩求和的时候,为了提高速度,可以在输入的时候先保存下来,就不用每次都去计算,不过再代码中没有写 另外这题不允许空矩阵,即至少 ...

  3. ural(Timus) 1463. Happiness to People!

    树DP 题意:输入n和m,表示n个城市,m条无向边,下面一行n个数字,表示每个城市的权值,下面m行是每条边的信息,u,v,w,顶点和边权.问你从一个城市出发,走出一条路线,使得权值和最大,权值和包括这 ...

  4. Ural(Timus) 1081. Binary Lexicographic Sequence

    DP(解码) 题意:给出一个串的长度n,串只有0,1组成,但是不能有两个相邻的1.按字典序给串排列,最先肯定是0000,接着是0001,依此类推.给一个数字m,输出在长度为n的情况下,第m个排列的串是 ...

  5. 线段树详解 (原理,实现与应用)

    线段树详解 By 岩之痕 目录: 一:综述 二:原理 三:递归实现 四:非递归原理 五:非递归实现 六:线段树解题模型 七:扫描线 八:可持久化 (主席树) 九:练习题 一:综述 假设有编号从1到n的 ...

  6. 【转载】线段树题目2

    1.hdu1166 敌兵布阵 更新节点,区间求和. 2.hdu1754 I Hate It 更新节点,区间最值. . 3.hdu1698 Just a Hook 成段更新,总区间求和. . 4.hdu ...

  7. pku,zju题目分类

    哎呦喂,直接ctrl+A了.话说浙江大学的题还见过的呢.. 公告: [意见反馈][官方博客]   ural pku Zju 题目分类 收藏   感谢 mugu 的提供.... Ural Problem ...

  8. 浅谈线段树(Segment Tree)

    线段树的概念与性质 线段树首先是一棵树,而且是二叉树.树上的每个节点对应于一个区间[a,b],a,b通常为整数.同一层的节点所代表的区间,互相不重叠.并且同一层的区间加起来是连续的区间,叶子节点的区间 ...

  9. 《题目与解读》红书 训练笔记目录《ACM国际大学生程序设计竞赛题目与解读》

    虽然2012年出版的老书了,但是是由三次世界冠军的上海交大ACM队出版的书籍,选择的题目是ACM经典中的经典,书中有非常详细的题解,可以学到很多东西,值得一刷. 目录 第一部分 第一章 数学 1.1 ...

最新文章

  1. 权限管理-SpringSecurity介绍
  2. Cloud for Customer系统里的附件url,可以通过partner编程自己生成么
  3. 1743. 从相邻元素对还原数组
  4. [bzoj1059]矩阵游戏
  5. 测试:脱离VS2010使用自动化测试时出现 6DA215C2-D80D-42F2-A514-B44A16DCBAAA 错误
  6. paip.输入法编程---带ord gudin去重复-
  7. MATLAB拟合函数
  8. html5网页制作的基本步骤,网页制作流程介绍
  9. ThreeJS 跨域
  10. 整车CAN网络基本结构
  11. 2021各厂免费云服务器申请攻略(阿里云/腾讯云/华为云)
  12. 语音识别平台_语音识别 平台_微信语音识别开放平台 - 云+社区 - 腾讯云
  13. XYplorer 23多语言,最好的管理软件之一
  14. 嫁给通信旺的16条理由!!!
  15. Transflow安装时弹出错误:You are using pip version 9.0.1, however version 19.1.1 is available. You should co
  16. 论“期权股”的财富经 !!!
  17. 我学炒外汇 第二十一篇波浪理论
  18. 阿里云服务器远程桌面连接
  19. 百度服务器保存信息多久,百度快照在百度服务器里保存多长时间???
  20. mysql 1443_MySQL 1443:這是什么意思?

热门文章

  1. 响应式设计PageAdmin个人博客系统源码v4.0.10
  2. SpringBoot集成logback彩色日志配置以及banner启动设置(炫酷到爆炸!)
  3. Magento教程 13:在Magento中设定联络表单的收件信箱
  4. Magento教程 2:Magento 社群版安装教学!
  5. Magento 创建优惠卷 Create unique coupon code in Magento
  6. UIView的一些基本方法 init、loadView、viewDidLoad、viewDidUnload、dealloc
  7. PHP RSS/Feed 生成类库(支持RSS 1.0/2.0和ATOM)
  8. MySQL in 查询,并通过 FIELD 函数按照查询条件顺序返回结果
  9. 本地Vue前端请求本地Spring Boot跨域问题(CROS错误)
  10. Nginx学习之九-负载均衡(客户端请求与Nginx进程间负载均衡)