题意:

      给你一个初始序列,初始序列长度n,分别为1 2 3 4 5 ....n,有两种操作

(1)D l r 把l_r之间的数据都复制一遍 1 2 3 4 5 6 D 2 4 = 1 2 2 3 3 4 4 5 6

(2)Q l r 询问lr之间的数字出现的最大次数 1 2 2 3 3 4 4 4 5 Q 1 3 = 2

思路:

      这个题目可以用线段树来解决,我们可以建一棵树1--n的,这个题目要注意一点就是无论怎么复制,所有的数字依然是连续的,对于线段树的每一个节点,我们有两个权值,区间元素个数,区间元素出现次数最大值,这样每次遇到一个区间,我们就把这个区间拆成三部分,左边的点,中间部分,右边的一个点,两边的用点更新,中间部分用段更新,每次给一个范围我们就可以根据这个范围找到范围所涉及到的数字范围(1--n),比如

11223344445555 现在给出范围3 13 =则找到的范围是2-5,这样点2,5单独处理,3-4用段更新处理,找的过程中我用的是深搜找的,对于每个点的信息,其实可以再深搜里直接一起找出来,但是我自己当初没想到,直接又多写了一个断询问,虽然麻烦点,但也AC了,具体的看代码吧!


#include<stdio.h>
#include<string.h> #define lson l ,mid ,t << 1
#define rson mid + 1 ,r ,t << 1 | 1
#define N_node 200000

__int64
sum[N_node] ,max[N_node] ,mark[N_node]; __int64 maxx(__int64 x ,__int64 y)
{
return
x > y ? x : y;
} void
Pushup(__int64 t)
{

sum[t] = sum[t<<1] + sum[t<<1|1];
max[t] = maxx(max[t<<1] ,max[t<<1|1]);
} void
Pushdown(__int64 t)
{
if(
mark[t])
{

mark[t<<1] += mark[t];
mark[t<<1|1] += mark[t];
sum[t<<1] <<= mark[t];
sum[t<<1|1] <<= mark[t];
max[t<<1] <<= mark[t];
max[t<<1|1] <<= mark[t];
mark[t] = 0;
} } void
BuidTree(__int64 l ,__int64 r ,__int64 t)
{

max[t] = sum[t] = mark[t] = 0;
if(
l == r)
{

max[t] = sum[t] = 1;
return;
}
__int64
mid = (l + r) >> 1;
BuidTree(lson);
BuidTree(rson);
Pushup(t);
} void
Update_1(__int64 l ,__int64 r ,__int64 t ,__int64 a ,__int64 b)
{
//点更新
if(l == r)
{

max[t] += b;
sum[t] += b;
return;
}

Pushdown(t);
__int64
mid = (l + r) >> 1;
if(
a <= mid) Update_1(lson ,a ,b);
else
Update_1(rson ,a ,b);
Pushup(t);
} void
Update_2(__int64 l ,__int64 r ,__int64 t ,__int64 a ,__int64 b)
{
//段更新
if(a <= l && b >= r)
{

sum[t] *= 2;
max[t] *= 2;
mark[t] ++;
return;
}

Pushdown(t);
__int64
mid = (l + r) >> 1;
if(
a <= mid) Update_2(lson ,a ,b);
if(
b > mid) Update_2(rson ,a ,b);
Pushup(t);
} __int64
Query_1(__int64 l ,__int64 r ,__int64 t ,__int64 a ,__int64 b)
{
//段查找,区间最大值
if(a <= l && b >= r)
return
max[t];
Pushdown(t);
__int64
mid = (l + r) >> 1;
__int64
now = 0;
if(
a <= mid) now = Query_1(lson ,a ,b);
if(
b > mid) now = maxx(now ,Query_1(rson ,a ,b));
return
now;
} __int64
Query_2(__int64 l ,__int64 r ,__int64 t ,__int64 a ,__int64 b)
{
//段查找,区间和
if(a <= l && b >= r)
return
sum[t];
Pushdown(t);
__int64
mid = (l + r) >> 1;
__int64
now = 0;
if(
a <= mid) now = Query_2(lson ,a ,b);
if(
b > mid) now += Query_2(rson ,a ,b);
return
now;
} __int64
DFS_Find(__int64 l ,__int64 r ,__int64 t ,__int64 now ,__int64 ss)
{
//深搜查找范围所在的点
if(l == r) return l;
Pushdown(t);
__int64
mid = (l + r) >> 1;
if(
now <= sum[t<<1] + ss)return DFS_Find(lson ,now ,ss);
else return
DFS_Find(rson ,now ,ss + sum[t<<1]);
} int main ()
{
int
t ,cas = 1 ,n ,m ,i;
__int64
a ,b;
char
str[5];
scanf("%d" ,&t);
while(
t--)
{

scanf("%d %d" ,&n ,&m);
BuidTree(1 ,n ,1);
printf("Case #%d:\n" ,cas ++);
for(
i = 1 ;i <= m ;i ++)
{

scanf("%s %I64d %I64d" ,str ,&a ,&b);
__int64
l = DFS_Find(1 ,n ,1 ,a ,0);
__int64
r = DFS_Find(1 ,n ,1 ,b ,0);
if(
str[0] == 'D')
{
if(
l == r)
{

Update_1(1 ,n ,1 ,l ,b - a + 1);
continue;
}
__int64
ls = Query_2(1 ,n ,1 ,1 ,l) - a + 1;
__int64
rs = b - Query_2(1 ,n ,1 ,1 ,r - 1);
Update_1(1 ,n ,1 ,l ,ls);
Update_1(1 ,n ,1 ,r ,rs);
if(
r - l > 1)
Update_2(1 ,n ,1 ,l + 1 ,r - 1);
}
else
{
if(
l == r)
{

printf("%I64d\n" ,b - a + 1);
continue;
}
__int64
now = 0;
__int64
ls = Query_2(1 ,n ,1 ,1 ,l) - a + 1;
__int64
rs = b - Query_2(1 ,n ,1 ,1 ,r - 1);
if(
r - l > 1) now = Query_1(1 ,n ,1 ,l + 1 ,r - 1);
if(
now < ls) now = ls;
if(
now < rs) now = rs;
printf("%I64d\n" ,now);
}
}
}
return
0;
}

hdu4973 线段树(题目不错,用了点,段,更新查找还有DFS)的更多相关文章

  1. 【ACM/ICPC2013】线段树题目集合(一)

    前言:前一段时间在网上找了一个线段树题目列表,我顺着做了一些,今天我把做过的整理一下.感觉自己对线段树了解的还不是很深,自己的算法能力还要加强.光练代码能力还是不够的,要多思考.向队友学习,向大牛学习 ...

  2. 嗯 第二道线段树题目 对左右节点和下标有了更深的理解 hdu1556

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. 线段树 & 题目

    首先说下我写的线段树吧. 我是按照线段树[完全版]那个人的写法来写的,因为网上大多数题解都是按照他的写法来写. 确实比较飘逸,所以就借用了. 节点大小是maxn是4倍,准确来说是大于maxn的2^x次 ...

  4. Balanced Lineup(最简单的线段树题目)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 33389   Accepted: 15665 Case Time Limit ...

  5. HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询

    题意: T个测试数据 n个数 q个查询 n个数 ( 下标从0开始) Q u v 查询 [u, v ] 区间最长连续上升子序列 U u v 把u位置改成v #include<iostream> ...

  6. [kuangbin带你飞]专题七 线段树

            ID Origin Title 228 / 440 Problem A HDU 1166 敌兵布阵   207 / 438 Problem B HDU 1754 I Hate It   ...

  7. hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)

    http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others)    ...

  8. bzoj4196 [Noi2015]软件包管理器 树链剖分+线段树

    先把树剖分了(又是dfs1.dfs2),然后区间求和.区间覆盖即可 难得的1A好(shui)题 ——写了那么多题,终于有一道是1A的了,加上上一次连续交了几遍A的程序,我的状态莫名好看啊233 总结: ...

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

    题目链接:http://poj.org/problem?id=2528 题目大意:有一个很上的面板, 往上面贴海报, 问最后最多有多少个海报没有被完全覆盖 解题思路:将贴海报倒着想, 对于每一张海报只 ...

随机推荐

  1. Java 语言基础 02

    语言基础·二级 顺序结构语句 * A:什么是流程控制语句    * 流程控制语句:可以控制程序的执行流程. * B:流程控制语句的分类    * 顺序结构    * 选择结构    * 循环结构 *  ...

  2. Hi3359AV100 NNIE开发(1)-RFCN demo LoadModel函数与参数解析

    之后随笔将更多笔墨着重于NNIE开发系列,下文是关于Hi3359AV100 NNIE开发(1)-RFCN demo LoadModel函数与参数解析,通过对LoadModel函数的解析,能够很好理解. ...

  3. Celery:小试牛刀

    Celery是如何工作的? Celery 由于 其分布式体系结构,在某种程度上可能难以理解.下图是典型Django-Celery设置的高级示意图(FROM O'REILLY): 当请求到达时,您可以在 ...

  4. Java多线程之线程

    前言 线程作为现代操作系统调度的最小单元,多个线程能够同时执行,这将显著提高程序的性能,而且在当前多核CPU的环境下也能更好的利用资源.Java提供了对多线程的良好支持.线程是多线程的基础. 使用多线 ...

  5. 浅谈Dotnet的数据定位和匹配

    Dotnet里,数据定位和匹配的相关编程现在变得很舒服.   最近项目紧,还要不停出差. 所以,写个短点的.最近经常用到的内容:数据定位和匹配.   数据定位 假设我们有这样一个数组: var arr ...

  6. Shell编程中变量用法

    1. 变量替换 语法 说明 ${变量名#匹配规则} 从变量开头进行规则匹配,将符合最短的数据删除 ${变量名##匹配规则} 从变量开头进行规则匹配,将符合最长的数据删除,贪婪匹配 ${变量名%匹配规则 ...

  7. Apache配置 1. 默认虚拟主机

    编辑httpd.conf搜索httpd-vhosts,去掉#号 # vi /usr/local/apache2.4/conf/httpd.conf Include conf/extra/httpd-v ...

  8. Docker安装完成后启动报错:Failed to start Docker Application Container Engine

    报错如下:显示没有启动 先关闭防火墙:防火墙关闭指令请看  <a href="Linux防火墙篇">https://www.cnblogs.com/szx666/p/1 ...

  9. STM32内存结构介绍和FreeRTOS内存分配技巧

    这是我第一次使用FreeRTOS构建STM32的项目,踩了好些坑,又发现了我缺乏对于操作系统的内存及其空间的分配的知识,故写下文档记录学习成果. 文章最后要解决的问题是,如何恰当地分配FreeRTOS ...

  10. Linux标准输入、重定向与参数传递

    Linux标准输入.重定向与参数传递 按惯例,每当运行一个新程序时,所有shell都为其打开3个文件描述符,即标准输入.标准输出以及标准错误.如果不做特殊处理,例如就像简单的命令ls,则这三个描述符都 ...