HDU5997 【线段树】
思路:
用vector存一下各种颜色的区间,每次处理颜色的区间,相同颜色不需要更新。区间最多1e6个没错,但是随着颜色的更替区间只会越来越少。
维护区间左右两端的颜色,lazy一下。
区间合并的时候 sum= sum_left + sum_right , 如果左儿子的区间右边和右儿子的区间左边颜色相同 sum--。
复杂度:don't know;
- #include<bits/stdc++.h>
- using namespace std;
- const int N=1e5+10;
- struct Seg{
- int Sum;
- int Lazy;
- int Left,Right;
- int Left_Color,Right_Color;
- }q[N*4];
- struct asd{
- int Left,Right;
- };
- vector<asd>eg[1000000+10];
- int col[N];
- void Pushdown(int num)
- {
- if(q[num].Lazy==-1) return;
- q[num<<1].Lazy=q[num<<1|1].Lazy=q[num].Lazy;
- q[num<<1].Sum=q[num<<1|1].Sum=1;
- q[num<<1].Left_Color=q[num<<1].Right_Color=q[num].Lazy;
- q[num<<1|1].Left_Color=q[num<<1|1].Right_Color=q[num].Lazy;
- q[num].Lazy=-1;
- }
- void Build(int num,int Left,int Right)
- {
- q[num].Left=Left;q[num].Right=Right;q[num].Lazy=-1;
- if(Left == Right){
- q[num].Sum=1;
- q[num].Left_Color=q[num].Right_Color=col[Left];
- return;
- }
- int Mid=(Left+Right)>>1;
- Build(num<<1,Left,Mid);
- Build(num<<1|1,Mid+1,Right);
- q[num].Left_Color=q[num<<1].Left_Color;
- q[num].Right_Color=q[num<<1|1].Right_Color;
- if(q[num<<1].Right_Color == q[num<<1|1].Left_Color)
- q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum-1;
- else
- q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
- }
- int Query(int num,int Left,int Right)
- {
- if(q[num].Left>=Left && q[num].Right<=Right) return q[num].Sum;
- Pushdown(num);
- int Mid=(q[num].Left+q[num].Right)>>1;
- if(Mid>=Right)
- return Query(num<<1,Left,Right);
- else if(Mid<Left)
- return Query(num<<1|1,Left,Right);
- else{
- int ans=0;
- ans+=Query(num<<1,Left,Mid);
- ans+=Query(num<<1|1,Mid+1,Right);
- if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) ans--;
- return ans;
- }
- }
- void Update(int num,int Left,int Right,int Color)
- {
- if(Left<=q[num].Left && q[num].Right<=Right){
- q[num].Lazy=Color;
- q[num].Sum=1;
- q[num].Left_Color=q[num].Right_Color=Color;
- return;
- }
- Pushdown(num);
- int Mid=(q[num].Left+q[num].Right)>>1;
- if(Mid>=Right)
- Update(num<<1,Left,Right,Color);
- else if(Mid<Left)
- Update(num<<1|1,Left,Right,Color);
- else
- {
- Update(num<<1,Left,Mid,Color);
- Update(num<<1|1,Mid+1,Right,Color);
- }
- q[num].Left_Color=q[num<<1].Left_Color;
- q[num].Right_Color=q[num<<1|1].Right_Color;
- q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
- if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) q[num].Sum--;
- }
- void init(int n)
- {
- for(int i=0;i<=1000000;i++)
- eg[i].clear();
- asd temp;
- int Color,Pre_Color=-1;
- for(int i=1;i<=n;i++)
- {
- scanf("%d",&Color);
- col[i]=Color;
- if(Pre_Color==-1){
- temp.Left=i;
- Pre_Color=Color;
- }
- else if(Pre_Color!=Color){
- temp.Right=i-1;
- eg[Pre_Color].push_back(temp);
- temp.Left=i;
- Pre_Color=Color;
- }
- }
- temp.Right=n;
- eg[Pre_Color].push_back(temp);
- Build(1,1,n);
- }
- void solve(int n)
- {
- asd temp;
- int Left,Right,x,y;
- int op;
- while(n--)
- {
- scanf("%d",&op);
- if(op==1)
- {
- scanf("%d%d",&x,&y);
- if(x==y) continue;
- int sz=eg[x].size();
- for(int i=0;i<sz;i++)
- {
- temp=eg[x][i];
- Update(1,temp.Left,temp.Right,y);
- eg[y].push_back(eg[x][i]);
- }
- eg[x].clear();
- }
- else
- {
- scanf("%d%d",&Left,&Right);
- printf("%d\n",Query(1,Left,Right));
- }
- }
- }
- int main()
- {
- int n,T,Q;
- scanf("%d",&T);
- while(T--)
- {
- scanf("%d%d",&n,&Q);
- init(n);
- solve(Q);
- }
- return 0;
- }
HDU5997 【线段树】的更多相关文章
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
- codevs 1080 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
- PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树
#44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...
- CF719E(线段树+矩阵快速幂)
题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作 分析:线段树 线段树的每个节点表示(f[i],f[i-1])这 ...
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
随机推荐
- 压力测试工具ab,wrk,locust简介
ab 无疑是目前最常见的压力测试工具.其典型用法如下: shell> ab -k -c 100 -t 10 http://domain/path 其中,参数「c」表示的是并发, 参数「t」表示的 ...
- 解析java.math.BigInteger类——构造函数
最早由于做作业,结识了java的BigInrger类.读着读着,越来越觉得有趣.后来作业做完,也不忍丢下它,索性把全部代码研究一遍. 开始的时候,一个上午时间最多读懂2个方法.但是还是有滋有味的坚持了 ...
- apktool + eclipse 动态调试APK
用了会AndBug,尽管挺强大的可是作为习惯了OD.EDB作为动态调试工具的人,自然有些不习惯,于是乎寻求新的动态调试解决方式.但大多数都是NetBeans + apktool.想着还得多下一个IDE ...
- SQL JOIN--初级篇
写在前面的话: 以下是最简单的join原理,为后面的大数据分布式join做概念复习和知识铺垫: 有时为了得到完整的结果,我们需要从两个或更多的表中获取结果.我们就需要执行 join. JOIN: 如果 ...
- unity导出android项目
1. 2 . 3 选择Google Android Project(若不选则直接导出Apk) Export,Android项目即可导出成功.
- android中getWidth()和getMeasuredWidth()
getMeasuredWidth()获取的是view原始的大小,也就是这个view在XML文件中配置或者是代码中设置的大小.getWidth()获取的是这个view最终显示的大小,这个大小有可能等于原 ...
- [NOIP2011提高组day2]-2-聪明的质监员
2.聪明的质监员(qc.cpp/c/pas) [问题描述] 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到 n 逐一编号,每个矿石都有自己的重量 wi 以及价 ...
- RobotFramework教程使用笔记——RIDE的相关知识及Resources创建关键字文件
RIDE是robotframework的图形操作前端,我们在RIDE上进行测试用例设计和编写测试脚本,并执行自动化测试.下面来全面的认识下这个操作工具. 在右边编辑页面有三大模块,Edit,TextE ...
- top命令按内存和cpu排序
目录 按进程的CPU使用率排序 按进程的内存使用率排序 按进程的CPU使用率排序 运行top命令后,键入大写P. 有两种途径: a) 打开大写键盘的情况下,直接按P键 b) 未打开大写键盘的情况下,S ...
- 调试windows服务最简单的方法之一
先看一下这段启动代码: using System; using System.Collections.Generic; using System.Linq; using System.ServiceP ...