洛谷 P1903 [国家集训队]数颜色 解题报告
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 [国家集训队]数颜色 解题报告的更多相关文章
- BZOJ2120/洛谷P1903 [国家集训队] 数颜色 [带修改莫队]
BZOJ传送门:洛谷传送门 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R ...
- ●洛谷P1903 [国家集训队]数颜色
题链: https://www.luogu.org/problemnew/show/P1903题解: 序列带修莫队, 推荐博客https://www.cnblogs.com/Paul-Guderian ...
- 洛谷 P1903 [国家集训队]数颜色 / 维护队列
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. \(Q\) \(L\) \(R\) 代表询问你从第L支画笔到第R支画笔中共有几种不同 ...
- [洛谷P1903][国家集训队]数颜色
题目大意:有$n$支画笔,有两个操作 $Q\;l\;r:$询问$[l,r]$中有几种颜色 $R\;p\;Col:$把第$p$支画笔的颜色改成$Col$ 题解:带修莫队,分为$n^{\frac{1}{3 ...
- 洛谷P1903 [国家集训队]数颜色 / 维护队列 ( 带 修 )
题意:有两种操作: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col. 对每个1操作 输出答案: 带修莫队 模板题 (加 ...
- 洛谷 P1903 [国家集训队]数颜色 / 维护队列 带修莫队
题目描述 墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: \(1\). \(Q\) \(L\) \(R\)代表询问你从第\(L\) ...
- 洛谷 P1903 [国家集训队]数颜色
题意简述 给定一个数列,支持两个操作 1.询问l~r有多少不同数字 2.修改某个数字 题解思路 带修莫队 如果修改多了,撤销修改 如果修改少了,进行修改 代码 #include <cmath&g ...
- 洛谷 P1407 [国家集训队]稳定婚姻 解题报告
P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...
- 洛谷 P1852 [国家集训队]跳跳棋 解题报告
P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...
随机推荐
- Python学习之购物车
实现功能: 程序启动,提示用户输入用户名和密码,程序读取余额文件last_salary.txt内容(文件不存在则自动创建),若文件内容为空则提示“首次登录,请输入工资”: 用户可以输入商品编号进行购买 ...
- C++ 基础 初始化列表
当一个类组合了其他类,或者使用了 const 成员,就要用 初始化列表. Class A {...}; Class B {...}; Class C { private: A a; B b; int ...
- python基础之继承组合应用、对象序列化和反序列化,选课系统综合示例
继承+组合应用示例 1 class Date: #定义时间类,包含姓名.年.月.日,用于返回生日 2 def __init__(self,name,year,mon,day): 3 self.name ...
- java实时监听日志写入kafka
目的 实时监听某目录下的日志文件,如有新文件切换到新文件,并同步写入kafka,同时记录日志文件的行位置,以应对进程异常退出,能从上次的文件位置开始读取(考虑到效率,这里是每100条记一次,可调整) ...
- Oozie 安装及 examples app 的使用
参考文档 一.Building OOzie 特别注意的是修改Pom.xml文件中的版本与本机中安装的版本相同 二. install Oozie 1.为 hadoop 添加 Oozie 的代理用户,添加 ...
- P2344 奶牛抗议
P2344 奶牛抗议 题目背景 Generic Cow Protests, 2011 Feb 题目描述 约翰家的N 头奶牛正在排队游行抗议.一些奶牛情绪激动,约翰测算下来,排在第i 位的奶牛的理智度为 ...
- (1)strchr
const char * strchr ( const char * str, int character ); char * strchr ( char * str, int character ) ...
- linux下vi的复制,黏贴,删除,撤销,跳转等命令-费元星
前言 在嵌入式linux开发中,进行需要修改一下配置文件之类的,必须使用vi,因此,熟悉 vi 的一些基本操作,有助于提高工作效率. 一,模式vi编辑器有3种模式:命令模式.输入模式.末行模式. ...
- linux 广播
广播是一台主机向局域网内的所有主机发送数据.这时,同一网段的所有主机都能接收到数据.发送广播包的步骤大致如下: (1)确定一个发送广播的接口,如eth0 (2)确定广播的地址,通过ioctl函数,请求 ...
- erlang连接mysql [转]
转自: http://blog.csdn.net/flyinmind/article/details/7740540 项目中用到erlang,同时也用到mysql.惯例,google. 但是,按照网上 ...