BZOJ2120:数颜色
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2120
对于区间内颜色种类数有一个百用不倦的套路,那就是只有每种颜色只有最左/右边算数,其它都算没颜色。
这一题也是一样,对于每个位置,我记录一下\(nxt[i]\)表示下一个离\(i\)最近的颜色与\(i\)相同的位置在哪。问题就变成了询问在区间\([l,r]\)内,有多少位置的\(nxt\)是大于\(r\)的了。用二维线段树就轻松解决了。
时间复杂度:\(O(nlog^2n)\)
空间复杂度:\(O(nlog^2n)\)
代码如下:
#include <set>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=5e4+5,maxv=1e6+5;
int n,m;
char ch[5];
int a[maxn];
set<int>s[maxv];
set<int>::iterator it;
int lst[maxn],nxt[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct nxt_segment_tree {
int tot;
int sum[maxn*100],ls[maxn*100],rs[maxn*100];
void change(int p,int l,int r,int pos,int v) {
while(1) {
sum[p]+=v;
if(l==r)break;
int mid=(l+r)>>1;
if(pos<=mid) {
if(!ls[p])ls[p]=++tot;
p=ls[p],r=mid;
}
else {
if(!rs[p])rs[p]=++tot;
p=rs[p],l=mid+1;
}
}
}
int query(int p,int l,int r,int pos) {
int res=0;
while(l!=r) {
int mid=(l+r)>>1;
if(pos<=mid) {
res+=sum[rs[p]];
r=mid,p=ls[p];
}
else l=mid+1,p=rs[p];
}
return res;
}
}T_inside;
struct pos_segment_tree {
int rt[maxn<<2];
void change(int p,int l,int r,int pos,int v,int opt) {
while(1) {
if(!rt[p])rt[p]=++T_inside.tot;
T_inside.change(rt[p],0,n+1,v,opt);
if(l==r)return;int mid=(l+r)>>1;
if(pos<=mid)r=mid,p=p<<1;
else l=mid+1,p=p<<1|1;
}
}
int query(int p,int l,int r,int L,int R,int v) {
if(L<=l&&r<=R)return T_inside.query(rt[p],0,n+1,v);
int mid=(l+r)>>1,res=0;
if(L<=mid)res+=query(p<<1,l,mid,L,R,v);
if(R>mid)res+=query(p<<1|1,mid+1,r,L,R,v);
return res;
}
}T_outside;
int main() {
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read(),s[a[i]].insert(i);
for(int i=1;i<=n;i++)
if(!s[a[i]].empty()) {
s[a[i]].insert(0);
s[a[i]].insert(n+1);
}
for(int i=1;i<=1000000;i++)
for(it=s[i].begin();it!=s[i].end();it++) {
int pos=*it;
if(pos==0||pos==n+1)continue;
if(pos!=0) {it--,lst[pos]=*it,it++;}
if(pos!=n+1) {it++,nxt[pos]=*it,it--;}
T_outside.change(1,1,n,pos,nxt[pos],1);
}
for(int i=1;i<=m;i++) {
scanf("%s",ch+1);
if(ch[1]=='Q') {
int l=read(),r=read();
printf("%d\n",T_outside.query(1,1,n,l,r,r));
}
else {
int pos=read(),col=read();
if(s[col].empty())s[col].insert(0),s[col].insert(n+1);
int x=lst[pos],y=nxt[pos];
if(x)T_outside.change(1,1,n,x,pos,-1),T_outside.change(1,1,n,x,y,1);
T_outside.change(1,1,n,pos,y,-1);nxt[x]=y,lst[y]=x;
it=s[a[pos]].find(pos),s[a[pos]].erase(it);
it=s[col].lower_bound(pos),y=*it,it--,x=*it,s[col].insert(pos);
if(x)T_outside.change(1,1,n,x,y,-1),T_outside.change(1,1,n,x,pos,1);
T_outside.change(1,1,n,pos,y,1);
nxt[x]=pos,nxt[pos]=y,lst[y]=pos,lst[pos]=x;
a[pos]=col;
}
}
return 0;
}
BZOJ2120:数颜色的更多相关文章
- BZOJ2120 数颜色 【带修莫队】
BZOJ2120 数颜色 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到 ...
- bzoj2120 数颜色 莫队 带修改
[bzoj2120]数颜色 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔 ...
- BZOJ2120 数颜色 【带修改莫队】
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MB Submit: 6579 Solved: 2625 [Submit][Status][Discus ...
- BZOJ2120 数颜色 —— 待修改莫队
题目链接:https://vjudge.net/problem/HYSBZ-2120 2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: ...
- BZOJ2120 数颜色(树套树)
B. 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令:1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色 ...
- [Bzoj2120]数颜色 (非正解 )(莫队)
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 6286 Solved: 2489[Submit][Status][Discuss] ...
- BZOJ2453维护队列&&BZOJ2120数颜色
2016-05-28 11:20:22 共同的思路: 维护某种颜色上一次在哪里出现pre,可以知道当pre<询问的l时更新答案 块内按照pre排序 修改的时候重新O(n)扫一遍,如果和之前的不一 ...
- bzoj2120: 数颜色(BIT套主席树+set/分块)
带修改的 HH的项链. 带修改考虑用BIT套主席树,查区间里有几个不同的数用a[i]上次出现的位置pre[i]<l的数有几个来算就好了. 考虑怎么修改.修改i的时候,我们需要改变i同颜色的后继的 ...
- BZOJ2120 数颜色(带修改莫队)
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- BZOJ2120 数颜色
Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成 一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同 ...
随机推荐
- Java学习笔记——java介绍
Java开源语言 C语言闭源语言 IOS闭源系统 采用object-c语言开发 应用程序分类(从类型分类) C/S(Client Server):不联网的软件也属于C/S B/S(Browser S ...
- EF中几个重要的类:ObjectContext、ObjectQuery、ObjectStateEntry、ObjectStateManager
ObjectContext封装 .NET Framework 和数据库之间的连接.此类用作“创建”.“读取”.“更新”和“删除”操作的网关. ObjectContext 类为主类,用于与作为对象(这些 ...
- bug_1——oracle listagg():列转行
select listagg(字段名 ,',') within group (order by 字段名) from表 where 条件 listagg():列转行 WM_CONCAT():和并列 ...
- CentOS iSCSI服务器搭建------LUN篇
先上服务器信息(你懂得) [root@node ~]# cat /etc/redhat-release CentOS release 6.6 (Final) [root@node ~]# uname ...
- Yii2 关于电子商务的开源项目
https://github.com/samdark/yii2-shop https://github.com/omnilight/yii2-shopping-cart https://github. ...
- JDK8新特性:接口的静态方法和默认方法
在jdk8之前,interface之中可以定义变量和方法,变量必须是public.static.final的,方法必须是public.abstract的.由于这些修饰符都是默认的,所以在JDK8之前, ...
- fastjson 格式化自定义选项
QuoteFieldNames———-输出key时是否使用双引号,默认为true WriteMapNullValue——–是否输出值为null的字段,默认为false WriteNullNumberA ...
- 仿联想商城laravel实战---4、验证(lavarel的表单验证如何使用)
仿联想商城laravel实战---4.验证(lavarel的表单验证如何使用) 一.总结 一句话总结: 验证规则和验证信息的数组:在控制器的方法中 1.注册页面中的用户名正确(比如是否重名,字段长度是 ...
- linux使用酷我在线听音乐
一般linux系统自带音频播放器只能管理本地音乐,无法在线听歌.在线音乐如百度音乐盒,下载歌曲需要登录,比较麻烦.在github里有一个酷我音乐的开源项目,可以安装在linux系统下.链接地址:htt ...
- EF学习 开始操作02
历史版本和未来版本 本文介绍有关实体框架 (EF5) 最新版本的信息,其中大部分内容也适用于旧版本.有关完整版本列表以及各版本引入的功能的详细信息,请参阅 “版本历史”. “历史版本”页面包含实体框架 ...