洛谷 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\), ...
随机推荐
- Centos 7 下安装mysql
// 卸载原有maridb-lib库 [root@localhost ~]# rpm -qa | grep mariadb mariadb-libs-5.5.41-2.el7_0.x86_64 [ro ...
- 《Linux就该这么学》,刘小伙实在人,给打个广告
本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...
- zip压缩工具,unzip解压缩工具
zip压缩工具,unzip解压缩工具=================== [root@aminglinux tmp]# yum install -y zip[root@aminglinux tmp] ...
- C语言基础篇(三) 指针
导航: 1.指针 2. 数组 3. 结构体,共用体 4. 内存分布图 5. 段错误分析 ----->x<------------->x<---- ...
- C——可变参数
1.要学可变参数,需要先了解C编译器对栈的管理 做个实验可以得到 #include <stdio.h> void func(int a, char b, int c, int d) { i ...
- P1219 N皇后
P1219 N皇后 题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上面的布局可以用序 ...
- 2018Ec-Final比赛总结
一场匆忙的旅程. NCC_9754_ Victory的最后一场比赛终究没能victory. 去的时候晕车到吐了两次,到宾馆吃完饭直接睡了,但还是两天都昏昏沉沉的头疼的厉害,第二天直接步行去了西工大体育 ...
- json loads/dumps
json.dumps : dict转成str json.loads:str转成dict dict_ = {1: 2, 3: 4, "} print(type(dict_), dict_) # ...
- Android getLocationInWindow
参考博客: http://blog.sina.com.cn/s/blog_44d19b500102vpve.html 这篇博客,我看了三遍,终于看懂了.恩,我就喜欢这样不放弃的自己. 1.getLoc ...
- [转]Android进程间通信--消息机制及IPC机制实现
Android为了屏蔽进程的概念,利用不同的组件[Activity.Service]来表示进程之间的通信! 组件间通信的核心机制是Intent,通过Intent可以开启一个Activity或Servi ...