hdu4973 线段树(题目不错,用了点,段,更新查找还有DFS)
题意:
给你一个初始序列,初始序列长度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)相关推荐
- 【转载】线段树题目2
1.hdu1166 敌兵布阵 更新节点,区间求和. 2.hdu1754 I Hate It 更新节点,区间最值. . 3.hdu1698 Just a Hook 成段更新,总区间求和. . 4.hdu ...
- 【转】线段树题目 汇总 讲解(by not only success)
转载自:http://www.notonlysuccess.com/ 非常喜欢他的代码风格以及简洁的思路,感谢notonlysuccess! PS:他的个人网站好像是上不去了-.- 线段树 很早前写的 ...
- poj 2528 离散化+线段树 hdu 1698 线段树 线段树题目类型一:染色计数 外加离散化
第一次听到离散化是今年省赛的时候,一道矩形并的题,很水,就两个矩形... 今天再去做线段树已经发现离散化忘得差不多了...水逼的悲哀啊... 先看简单点的hdu 1698 http://acm.hdu ...
- 【总结】一些简单线段树题目的口胡题解
bzoj1645 离散化+扫描线 tyvj1473 校门外的树3 思维僵化(非要套离线枚举右端点然而不好做)系列,直接容斥求不与[l,r][l,r][l,r]相交的线段个数即可 bzoj3653谈笑风 ...
- 【用学校抄作业带你走进可持久化线段树(主席树)】可持久化线段树概念+全套模板+例题入门:[福利]可持久化线段树)
我似乎很少写这种算法博客 可持久化线段树概念 概念介绍(类比帮助理解) 简单分析一下时间和空间复杂度(内容池) 模板 结构体变量 建树模板 单点修改模板 单点查询模板 区间修改模板(pushup) 区 ...
- 线段树——HDU - 1698
题目含义 就是初始化一堆数为1 可以经过操作把一个区间的数都改变 并求这堆数的总大小 题目分析 有一个 #include<iostream> #include<stdio.h> ...
- 暑期集训5:并查集 线段树 练习题F: HDU - 1166
2018学校暑期集训第五天--并查集 线段树 练习题F -- HDU - 1166 敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A ...
- Naive Operations (线段树 分析复杂度)
题目: 给出一个长度为n初值为0的数组,以及长度为n的b数组,然后q次操作,add(l,r) 使得区间l-r所有元素+1,或者查询l~r区间a[i]/b[i]的和 题解: 很少情况下能很快写出一道线段 ...
- 0x43.数据结构进阶 - 线段树
目录 一.基础线段树 线段树的建树 线段树的单点修改 线段树的区间查询 线段树的延迟标记(懒惰标记) 1.POJ3486 ASimpleProblemwithIntegersA\ Simple\ Pr ...
最新文章
- python hashlib模块_python-hashlib模块
- javascript 模块化机制
- 普通大学毕业后干啥_一名女孩从大学毕业后在机械行业干了十年,背后经历让人辛酸……...
- Mariadb升级到mysql_mariadb的版本升级方法
- 前端经常遇到的跨域问题几种解决方案
- php 文件 计数,文件计数问题
- BZOJ 4992: [Usaco2017 Feb]Why Did the Cow Cross the Road
- MyBatis学习(七)
- How to extract datafiles from asm diskgroup?
- 【安卓按键精灵】教你一个小时自己开发脚本,零基础1个小时上手
- Xshell_4.0绿色版
- 今夜,只我一人听雨声
- maven下载jar包下载不下来的解决方法
- Pooling Revisited: Your Receptive Field is Suboptimal 论文解读和感想
- 第3周学习:ResNet+ResNeXt
- ubuntu如何用快捷键截图
- uniapp安卓离线打包--手把手教会
- kind:Kubernetes in Docker,单机运行 Kubernetes 群集的最佳方案?
- EM算法-Jensen不等式
- 蔡高厅高等数学10 无穷大量与无界函数的关系、无穷大与无穷小的关系、海涅定理