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. js中document的用法小结

    document常用属性: document.title//设置文档标题,与HTNL中的title标签等价 document.bgColor//设置页面背景颜色 document.fgColor//设 ...

  2. Anaconda下安装 TensorFlow 和 keras 以及连接pycharm

    首先在官网下载Anaconda https://www.anaconda.com/download/ 安装时注意 勾选第一个,增加环境变量 安装好后再windows界面打开Anaconda Promp ...

  3. Redhat 6.4 linux系统不重启识别热添加的硬盘方法

    1.1    选择虚拟机添加一块硬盘 1.2    查看系统当前磁盘信息 [root@zhongyi-test ~]# ls -l /dev/sd* brw-rw----. 1 root disk 8 ...

  4. P1582倒水 位运算

    题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒 ...

  5. 在intellij idea 里来回跳转查询方法

    在intellij idea 里来回跳转查询方法,在不知道快捷键的时候真是抓狂. 看到key map中的快捷键 后退back  ctrl +alt + ← 或者button4 click 前进forw ...

  6. 笔记-docker-3 使用

    笔记-docker-3 使用 1.      镜像 image是docker最重要的概念,docker运行容器前需要本地存在对应的镜像,如果没有,会尝试从默认镜像库下载. 1.1.    镜像获取 查 ...

  7. 零基础学css第二天

    内边距与外边距: <!DOCTYPE html> <html> <head> <title></title> <style type= ...

  8. 用Mapreduce求共同好友

    import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs ...

  9. React-router4简约教程

    React-router4简约教程 教程       webEmmet 17年10月   React-router和React-router-dom的选择 很多刚使用react的同学在接触到react ...

  10. C语言库函数实现 【微软面试100题 第八十三题】

    题目要求 1.strcpy/memcpy/memmove: 2.memset函数: 3.字符串处理函数. 题目分析 1.接口定义: char * strcpy(char * dest, const c ...