思路:

用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 【线段树】的更多相关文章

  1. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  2. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  3. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  4. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  5. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  6. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  7. CF719E(线段树+矩阵快速幂)

    题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作 分析:线段树 线段树的每个节点表示(f[i],f[i-1])这 ...

  8. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  9. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  10. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

随机推荐

  1. Struts2 原理(转载)

    图来源于Struts2官方站点,是Struts 2 的整体结构. Struts2框架由3个部分组成:核心控制器FilterDispatcher.业务控制器和用户实现的业务逻辑组件.在这3个部分里,St ...

  2. EasyDarwin开源社区 短视频拍摄项目Github地址

    在前面的几篇博客中,我们提到了EasyDarwin开源团队整理出来的短视频拍摄技术要点,这次我们将短视频技术及SDK整理成一个完整的Github项目进行长期维护,同时会支持安卓Android和IOS版 ...

  3. exp/imp三种模式——完全、用户、表

    ORACLE数据库有两类备份方法.第一类为物理备份,该方法实现数据库的完整恢复,但数据库必须运行在归挡模式下(业务数据库在非归挡模式下运行),且需要极大的外部存储设备,例如磁带库:第二类备份方式为逻辑 ...

  4. Redis(三)位图

    1.目录 什么是位图 位图的作用 基本使用 2.什么是位图 位图不是一个真实的数据类型,而是定义在字符串类型上的面向位的操作的集合.由于字符串类型是二进制安全的二进制大对象,并且最大长度是 512MB ...

  5. TWinControl、TCustomControl和TGraphicControl对WM_PAINT消息的三种不同处理(虚函数的特点就是升升降降)

    -------------------- TWinControl收到WM_Paint消息(以后找个例子)-------------------- 1. 消息函数 TWinControl.WMPaint ...

  6. BZOJ3231: [Sdoi2008]递归数列

    BZOJ3231: [Sdoi2008]递归数列 Description 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + ...

  7. openstack之路:虚拟机的配置

    创建虚拟机有2种方法: 1 virt-manager. 优点:上手简单.缺点:实现自动化比较困难 2 virsh创建 优点:自动化配置简单.缺点:创建过程比较复杂 我们首先通过virt-manager ...

  8. 20170228 交货单过账增强 MV50AFZ1

    MV50AFZ1   这个程序里面找个FORM 用户出口, FORM USEREXIT_SAVE_DOCUMENT_PREPARE.   用户出口如下: 例:需求: 开发要求:制作交货单的人员,需要同 ...

  9. R in Action(0) 开篇

    这几年数据挖掘的火热,也越来越多的人把R作为数据挖掘的一个辅助工具,据国际性组织kkguter统计有60%的人在挖掘过程中用到R工具,可见这个工具是多么的流行,对于数据统计.筛选以及画图绝对是神器.尽 ...

  10. iOS信号量

    引子: 在取本地联系人列表的时候看到同事用的这么一段代码: dispatch_semaphore_t sema = dispatch_semaphore_create(); ABAddressBook ...