ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板)

题意

题意:给一个n,代表n次操作,接下来每次操作表示把[l,r]区间的线段涂成k的颜色其中,l,r,k的范围都是0到8000

这题比较坑的是不能拿n建树,不然就会segmentation fault,我也是错了好多遍看的博客才知道,必须拿8000建树,也就是树是固定的。

解题思路一

线段树来维护点的颜色

单点查询,从左到右一个一个点的查询,这个有点暴力,但是因为每次查询都是\(logn\)也不是很大,跑了一下是60ms

代码实现一

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=8e3+7;
struct node{
int l, r;
int lazy;
}a[maxn<<2];
int ans[8007];
void down(int rt)
{
int l=rt<<1, r=rt<<1|1; a[l].lazy=a[rt].lazy; a[r].lazy=a[rt].lazy; a[rt].lazy=-1;
}
void build(int rt, int l, int r)
{
a[rt].l=l;
a[rt].r=r;
a[rt].lazy=-1; //表示当前点的范围颜色不统一
if(l==r) return ;
int mid=(l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
}
void update(int rt, int L, int R, int x)
{
if(L<=a[rt].l && a[rt].r<=R)
{
a[rt].lazy=x;
return ;
}
int mid=(a[rt].l+a[rt].r)>>1;
if(a[rt].lazy!=-1)
down(rt);
if(L<=mid) update(rt<<1, L, R, x);
if(R>mid) update(rt<<1|1, L, R, x);
}
int query(int rt, int x) //单点查询
{
if(a[rt].l==a[rt].r)
{
return a[rt].lazy;
}
if(a[rt].lazy!=-1) //记得一定要down一下,因为是单点查询,如果不down,这个点可能还是上一次的状态
down(rt);
int mid=(a[rt].l+a[rt].r)>>1;
if(x<=mid) return query(rt<<1, x);
else return query(rt<<1|1, x);
}
int main()
{
int n, a, b, c;
while(scanf("%d", &n)!=EOF)
{
build(1, 1, 8000);
memset(ans, 0, sizeof(ans));
for(int i=1; i<=n; i++)
{
scanf("%d%d%d", &a, &b, &c);
update(1, a+1, b, c);
}
int p1, p2;
p1=query(1, 1);
if(p1!=-2 && p1!=-1) ans[p1]++;
for(int i=2; i<=8000; i++)
{
p2=query(1, i);
if(p1!=p2){
ans[p2]++;
}
p1=p2;
}
for(int i=0; i<=8000; i++)
{
if(ans[i]!=0)
{
printf("%d %d\n", i, ans[i]);
}
}
printf("\n");
}
return 0;
}

解题思路二

类似区间查询,如果某一个点的lazy标记不是-1,那个这个区间就都是一种颜色,就不用往下递归了

如果lazy是-2,那个这个区域没有颜色,相当于中间隔开了一块区域。

查询是从左到右进行的,pre表示先前点左边的颜色,需要判断当前点与左边的点的颜色是否相同。

这个代码跑的是50ms。

代码实现二

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=8e3+7;
struct node{
int l, r;
int lazy;
}a[maxn<<2];
int ans[8007];
int pre; //pre表示先前块的颜色
void down(int rt)
{
int l=rt<<1, r=rt<<1|1; a[l].lazy=a[rt].lazy; a[r].lazy=a[rt].lazy; a[rt].lazy=-1;
}
void build(int rt, int l, int r)
{
a[rt].l=l;
a[rt].r=r;
a[rt].lazy=-2; //表示没有颜色
if(l==r) return ;
int mid=(l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
}
void update(int rt, int L, int R, int x)
{
if(L<=a[rt].l && a[rt].r<=R)
{
a[rt].lazy=x;
return ;
}
int mid=(a[rt].l+a[rt].r)>>1;
if(a[rt].lazy!=-1 && a[rt].lazy!=-2)
down(rt);
if(L<=mid) update(rt<<1, L, R, x);
if(R>mid) update(rt<<1|1, L, R, x);
if(a[rt<<1].lazy==a[rt<<1|1].lazy)//相当于up 看下属左右两点的颜色是否相同
{
a[rt].lazy=a[rt<<1].lazy; //相同的话,这个点就可以代表下面的两个点
}
else a[rt].lazy=-1;//否则-1表示下属两个点的颜色不统一,需要以后特殊标记
}
void query(int rt)//先当于区间查询,从左到右
{
if(a[rt].lazy==-2) //说明这个点控制的区域没有刷颜色,那么它右边的点也可以和左边的点有相同颜色
{
pre=-1;//这个标记-1
return ; //结束
}
if(a[rt].lazy!=-1)
{
if(a[rt].lazy!=pre)
{
ans[a[rt].lazy]++;
pre=a[rt].lazy;
}
return ;
}
query(rt<<1);
query(rt<<1|1);
}
int main()
{
int n, a, b, c;
while(scanf("%d", &n)!=EOF)
{
build(1, 1, 8000);
memset(ans, 0, sizeof(ans));
for(int i=1; i<=n; i++)
{
scanf("%d%d%d", &a, &b, &c);
update(1, a+1, b, c);
}
pre=-2;
query(1);
for(int i=0; i<=8000; i++)
{
if(ans[i]!=0)
{
printf("%d %d\n", i, ans[i]);
}
}
printf("\n");
}
return 0;
}

ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板)的更多相关文章

  1. 关于使用lazytag的线段树两种查询方式的比较研究

    说到线段树,想来大家并不陌生——最基本的思路就是将其规划成块,然后只要每次修改时维护一下即可. 但是尤其是涉及到区间修改时,lazytag的使用往往能够对于程序的质量起到决定性作用(Ex:一般JSOI ...

  2. MVC EF两种查询方法

    @*@model IQueryable<EFExam.Models.Product>*@@model IQueryable<EFExam.Models.ProductViewMode ...

  3. [moka同学笔记]YII2.0 判断签约状态,sql的两种查询方法

    方法一: //判断签约状态 $signed = 0; $sql="SELECT * from usho_community_sign_record WHERE com_id=$r->i ...

  4. KbmMW两种查询结果集通讯方式

    KbmMW本身可以用QueryService的方式进行远程数据查询,但是SmpileService同样具有很强的扩展性可以实现数据查询,下面展示两种基于SmpileService的远程数据查询方法,其 ...

  5. LINQ to Objects系列(2)两种查询语法介绍

    LINQ为我们提供了两种查询语法,分别是查询表达式和查询方法语法.这篇文章分为以下几个方面进行总结. 1,一个包含两种查询语法的简单示例 2,查询表达式的结构 3,查询方法相关的运算符 一个包含两种查 ...

  6. JS中的两种刷新方法以及区别和适用范围

    在项目中有一个人信息修改的页面,但是修改后显示的却是修改之前的内容,分析问题后发现查询语句写在了修改语句之前,有些某些需要又必须这么写,但是修改信息后先却显示之前的信息也太不科学了. 所以我就想用js ...

  7. 两种js方法发起微信支付:WeixinJSBridge,wx.chooseWXPay区别

    原文链接:https://www.2cto.com/weixin/201507/412752.html 1.为什么会有两种JS方法可以发起微信支付? 当你登陆微信公众号之后,左边有两个菜单栏,一个是微 ...

  8. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  9. angular2系列教程(十)两种启动方法、两个路由服务、引用类型和单例模式的妙用

    今天我们要讲的是ng2的路由系统. 例子

随机推荐

  1. pdf幻灯片:圆锥曲线中的“三定”问题探究(一)

    预留的广告位! 下载该pdf文件,然后在adobe reader 的"视图"中使用"全屏模式"播放该幻灯片 #include <iostream> ...

  2. python-抽象类和抽象方法

    需要模块  import abc 抽象类不能实例化 import abc class Animal(metaclass=abc.ABCMeta): #抽象类 @abc.abstractmethod # ...

  3. Eclipse Debug模式的开启与关闭问题简析_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 默认情况下,eclipse中右键debug,当运行到设置的断点时会自动跳到debug模式下.但由于我的eclipse环境 ...

  4. React Native 之项目的启动

    运行项目有两种方法 1. 到根目录,执行 react-native run-ios 命令 会开启一个本地服务,加载jsbundle文件,然后是去index.js文件 import {AppRegist ...

  5. 错误: 找不到或无法加载主类 org.sang.BlogserverApplication

    错误: 找不到或无法加载主类 org.sang.BlogserverApplication

  6. HDU 4300 Clairewd's message ( 拓展KMP )

    题意 : 给你一个包含26个小写字母的明文密文转换信息字符串str,第一个表示'a'对应的密文是str[0].'b'对应str[1]……以此类推.接下来一行给你一个另一个字符串,这个字符串由密文+明文 ...

  7. [luogu]P2680 运输计划[二分答案][树上差分]

    [luogu]P2680 [NOIP2015]运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n ...

  8. 如何理解重载与重写——Overload vs Override/Overwrite

    重载: 在同一个类中,拥有类似功能的同名方法之间的关系叫做重载. 重载的条件:1.具有相同方法名和类似功能: 2.参数的类型或者个数不同: 3.与返回值无关: 重写: 在子父类的继承关系中,子类继承父 ...

  9. 3D Computer Grapihcs Using OpenGL - 10 Color Buffer

    本节我们将尝试利用三角形制作一个“走马灯”效果. 一个三角形如图示方式,从左向右依次移动. 先看一下代码: MyGlWindow.cpp #include <gl\glew.h> #inc ...

  10. Swift equality

    最后更新: 2017-07-23 在程序开发中,我们时常需要来判断两个对象是否相等.在编程思想中,两个对象相等指的是在内存中的地址相同,也就是两个指针指向同一个地址.但是在日常理解中,只要两个对象的内 ...