P1903 [国家集训队]数颜色

题目描述

墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

1、Q L R代表询问你从第\(L\)支画笔到第\(R\)支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第\(P\)支画笔替换为颜色\(Col\)。

为了满足墨墨的要求,你知道你需要干什么了吗?

输入输出格式

输入格式:

第1行两个整数\(N\),\(M\),分别代表初始画笔的数量以及墨墨会做的事情的个数。

第2行\(N\)个整数,分别代表初始画笔排中第i支画笔的颜色。

第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

输出格式:

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

说明

对于100%的数据,N≤50000,M≤50000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。


正解是待修莫队,不过树套树复杂度更优秀(常数就不一定了),就拿树套树过了这个题

把一个颜色的笔放到一个set里,以位置为关键字,同时更新\(pre\)数组,代表前一个相同颜色的位置(特别的,如果没有,为0)

先不考虑修改,我们发现询问\([l,r]\)有多少不同颜色等价于询问有多少个\(pre\)数组小于\(l\),我们可以拿权值线段树解决这个问题

然后对于修改,我们只需要在外面套上树状数组就可以啦


Code:

#include <cstdio>
#include <algorithm>
#include <set>
#define ls ch[now][0]
#define rs ch[now][1]
using namespace std;
const int N=2e5+10;
int ch[N*18][2],sum[N*18],root[N],tot;
int a[N],b[N],pre[N],n,m,k;
void updata(int now){sum[now]=sum[ls]+sum[rs];}
void change(int &now,int l,int r,int pos,int delta)
{
if(!now) now=++tot;
if(l==r) {sum[now]+=delta;return;}
int mid=l+r>>1;
if(pos<=mid) change(ls,l,mid,pos,delta);
else change(rs,mid+1,r,pos,delta);
updata(now);
}
int query(int now,int l,int r,int pos)
{
if(!now||l==r) return 0;
int mid=l+r>>1;
if(pos<=mid) return query(ls,l,mid,pos);
else return sum[ls]+query(rs,mid+1,r,pos);
}
void modify(int x,int pos,int delta)
{
while(x<=n) change(root[x],0,n-1,pos,delta),x+=x&-x;
}
int ask(int x,int rk)
{
int ans=0;
while(x)
ans+=query(root[x],0,n-1,rk),x-=x&-x;
return ans;
}
struct node{int op,x,y;}opt[N];
set <int > rb[N];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
m=n;char c[3];
for(int i=1;i<=k;i++)
{
scanf("%s%d%d",c,&opt[i].x,&opt[i].y);
opt[i].op=(c[0]=='R');
if(opt[i].op) a[++m]=opt[i].y;
}
sort(a+1,a+1+m);
m=unique(a+1,a+1+m)-a-1;
for(int i=1;i<=n;i++) b[i]=lower_bound(a+1,a+1+m,b[i])-a;
for(int i=1;i<=k;i++) if(opt[i].op) opt[i].y=lower_bound(a+1,a+1+m,opt[i].y)-a;
for(int i=1;i<=n;i++)
{
if(!rb[b[i]].empty())
{
set <int>::iterator it=rb[b[i]].end();
it--;
pre[i]=*it;
}
rb[b[i]].insert(i);
}
for(int i=1;i<=n;i++)
for(int j=i-(i&-i)+1;j<=i;j++)
change(root[i],0,n-1,pre[j],1);
for(int i=1;i<=k;i++)
{
if(opt[i].op)
{
int co=opt[i].y,pos=opt[i].x,pr;
set <int >::iterator it=rb[b[pos]].find(pos);//找到颜色位置
it++;
if(it!=rb[b[pos]].end())//改它的后继
{
modify(*it,pos,-1);
modify(*it,pre[*it]=pre[pos],1);
}
rb[b[pos]].erase(pos);//删掉
rb[b[pos]=co].insert(pos);//加入且改自己颜色
it=rb[co].find(pos);
if(it!=rb[co].begin()) it--,pr=*it,it++;
else pr=0;//找到pre
modify(pos,pre[pos],-1);//改自己pre
modify(pos,pre[pos]=pr,1);
it++;
if(it!=rb[b[pos]].end())//寻找后面
{
modify(*it,pre[*it],-1);
modify(*it,pre[*it]=pos,1);
}
}
else
printf("%d\n",ask(opt[i].y,opt[i].x)-opt[i].x+1);
}
return 0;
}

2018.9.4

洛谷 P1903 [国家集训队]数颜色 解题报告的更多相关文章

  1. BZOJ2120/洛谷P1903 [国家集训队] 数颜色 [带修改莫队]

    BZOJ传送门:洛谷传送门 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R ...

  2. ●洛谷P1903 [国家集训队]数颜色

    题链: https://www.luogu.org/problemnew/show/P1903题解: 序列带修莫队, 推荐博客https://www.cnblogs.com/Paul-Guderian ...

  3. 洛谷 P1903 [国家集训队]数颜色 / 维护队列

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. \(Q\) \(L\) \(R\) 代表询问你从第L支画笔到第R支画笔中共有几种不同 ...

  4. [洛谷P1903][国家集训队]数颜色

    题目大意:有$n$支画笔,有两个操作 $Q\;l\;r:$询问$[l,r]$中有几种颜色 $R\;p\;Col:$把第$p$支画笔的颜色改成$Col$ 题解:带修莫队,分为$n^{\frac{1}{3 ...

  5. 洛谷P1903 [国家集训队]数颜色 / 维护队列 ( 带 修 )

    题意:有两种操作: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col. 对每个1操作 输出答案: 带修莫队 模板题 (加 ...

  6. 洛谷 P1903 [国家集训队]数颜色 / 维护队列 带修莫队

    题目描述 墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: \(1\). \(Q\) \(L\) \(R\)代表询问你从第\(L\) ...

  7. 洛谷 P1903 [国家集训队]数颜色

    题意简述 给定一个数列,支持两个操作 1.询问l~r有多少不同数字 2.修改某个数字 题解思路 带修莫队 如果修改多了,撤销修改 如果修改少了,进行修改 代码 #include <cmath&g ...

  8. 洛谷 P1407 [国家集训队]稳定婚姻 解题报告

    P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...

  9. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

随机推荐

  1. 【模板时间】◆模板·I◆ 倍增计算LCA

    [模板·I]LCA(倍增版) 既然是一篇重点在于介绍.分析一个模板的Blog,作者将主要分析其原理,可能会比较无趣……(提供C++模板) 另外,给reader们介绍另外一篇非常不错的Blog(我就是从 ...

  2. django连接mysql数据库配置,出现no module named mysqldb报错

    作为一个菜鸟运维也是要有梦想的,万一学会了python走向人生巅峰了呢.好吧,都是瞎想,今天主要介绍下django配置,最近也开始摸索这个牛b框架了,当然大佬肯定不屑一顾,都是照顾照顾我们这些菜鸟初学 ...

  3. avalon ms-repeat avalon1

    工作原因要用到avalon二次开发, 但是看了下以前的avalon版本是1,现在大多数都是2版本了吧,,所以很多文档不好找,但是大多数还是好用的 ms-repeat 循环当前赋值的, ms-repea ...

  4. 用ajax获取淘宝关键字接口

    可定需要查看淘宝界面的结构,按F12查看网页,此时先清除一下网页中的数据,让Network制空,随后在输入框中输入新的内容,比如钱包,数据中会出现新的数据.点击及查看蓝色方框中的内容 点击之后,你可以 ...

  5. 使用PHP生成分享图片

    小程序导航 wq.xmaht.top 假设代码中用到的资源文件夹在当前code_png目录下: /** * 分享图片生成 * @param $gData 商品数据,array * @param $co ...

  6. Linux编译移植Qt4的环境_在OMAPL138平台

    Linux编译Qt4的环境_OMAPL138 手里有一块创龙OMAPL138的板子,我要在上面成功移植Qt环境和触摸屏幕,这是我第二次进行Linux的Qt环境移植,发现了很多问题,需要重新整理. 我编 ...

  7. Python学习之高级特性

    切片 在Python基础篇里,我们知道Python的可序列对象可以通过索引号(下标)来引用对象元素,索引号可以由0开始从左向右依次获取,可以从-1开始由右向左获取.这种方法可以帮助我们依次获取我们想要 ...

  8. 树上dfs+思维

    #include<cstdio> ; int cnt,head[N],n; int size[N],num[N]; void init() { cnt = ; ;i<N;i++) h ...

  9. 20145202马超《Java程序设计》第十周学习总结

    一.网络编程 1.网络概述 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴.在发送和接收数据 ...

  10. 12,nginx+uWSGI+django+virtualenv+supervisor发布web服务器

    导论 WSGI是Web服务器网关接口.它是一个规范,描述了Web服务器如何与Web应用程序通信,以及Web应用程序如何链接在一起以处理一个请求,(接收请求,处理请求,响应请求) 基于wsgi运行的框架 ...