【BZOJ 2120】数颜色【分块/莫队】
题意
给出n个数字和m个操作。操作有两种。1:查询区间[l,r]内不同种类得数字个数。2: 将下标为p得数字修改为v
分析
如果不是修改操作的话,用莫队贼简单就可以水过,但是因为带了修改就有一些麻烦了。
分块
开一个数组pre[i]记录上一个和第i个元素相同元素得位置。那么对于区间[l,r],当pre[i]<l的时候,ans++。完整块内就可以直接二分查找,不完整块直接暴力。修改是直接暴力修改因为它保证修改操作不会超过1000次。
下面是代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int maxn=+;
int a[maxn],belong[maxn],L[maxn],R[maxn],pre[maxn];
int last[+],b[maxn]; int n,m,cnt,block;
void update(int p,int v){
for(int i=;i<=n;i++)
last[a[i]]=;
a[p]=v;
for(int i=;i<=n;i++){
b[i]=last[a[i]];
last[a[i]]=i;
}
for(int i=;i<=cnt;i++){
for(int j=L[i];j<=R[i];j++)
pre[j]=b[j];
sort(pre+L[i],pre+R[i]+);
}
}
int Find(int p,int v){
int res=;
int l=L[p],r=R[p];
while(l<=r){
int m=l+(r-l)/;
if(pre[m]<v){
res=m;
l=m+;
}else{
r=m-;
}
}
return res-L[p]+;
} int query(int l,int r){
int res=;
if(belong[l]==belong[r]){
for(int i=l;i<=r;i++){
if(b[i]<l)
res++;
}
return res;
}
for(int i=l;i<=R[belong[l]];i++)
if(b[i]<l)
res++; for(int i=L[belong[r]];i<=r;i++)
if(b[i]<l)
res++; for(int i=belong[l]+;i<belong[r];i++){
res+=Find(i,l);
}
return res;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
b[i]=last[a[i]];
last[a[i]]=i;
}
block=sqrt(n);cnt=n/block;
if(n%block)cnt++;
for(int i=;i<=n;i++)
belong[i]=(i-)/block+;
for(int i=;i<=cnt;i++)
L[i]=(i-)*block+,R[i]=i*block;
R[cnt]=n; for(int i=;i<=cnt;i++){
for(int j=L[i];j<=R[i];j++)
pre[j]=b[j];
sort(pre+L[i],pre+R[i]+);
}
char c;
int l,r;
for(int i=;i<=m;i++){
scanf(" %c",&c);
if(c=='Q'){
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r));
}else{
scanf("%d%d",&l,&r);
update(l,r);
}
}
return ;
}
莫队
对于莫队来说,难点就在于它带有修改操作。我们怎么来处理修改呢?我们在除了l,r指针以外再增加一个指针now,用类似l和r得方式进行维护。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath> using namespace std;
const int maxn=+;
int belong[maxn],val[maxn];
struct Node{
int L,R,id,tim;
bool operator<(const Node& rhs)const{
return belong[L]==belong[rhs.L]?(belong[R]==belong[rhs.R]?tim<rhs.tim:R<rhs.R):L<rhs.L;
}
int ans;
}ask[maxn];
struct Up{
int p,v,z;
}up[maxn];
int num1,num2;
int cmp(Node a,Node b){
return a.id<b.id;
}
int n,q;
int f[+],ans,block,l,r,now;
void update(int p,int addv){
if(addv>){
f[val[p]]++;
if(f[val[p]]==)
ans++;
}else{
f[val[p]]--;
if(f[val[p]]==)
ans--;
}
}
void in_time(int x){
if(up[x].p>=l&&up[x].p<=r){
update(up[x].p,-);
}
up[x].z=val[up[x].p];
val[up[x].p]=up[x].v;
if(up[x].p>=l&&up[x].p<=r){
update(up[x].p,);
}
}
void out_time(int x){
if(up[x].p>=l&&up[x].p<=r)
update(up[x].p,-);
val[up[x].p]=up[x].z;
if(up[x].p>=l&&up[x].p<=r)
update(up[x].p,);
} void solve(){
l=,r=,now=;
for(int i=;i<=num1;i++){
if(r<ask[i].R){
for(r=r+;r<ask[i].R;r++)
update(r,);
update(r,);
}
if(l>ask[i].L){
for(l=l-;l>ask[i].L;l--)
update(l,);
update(l,);
}
if(r>ask[i].R){
for(;r>ask[i].R;r--)
update(r,-);
}
if(l<ask[i].L){
for(;l<ask[i].L;l++)
update(l,-);
}
if(now<ask[i].tim){
for(now=now+;now<ask[i].tim;now++)
in_time(now);
in_time(now);
}
if(now>ask[i].tim){
for(;now>ask[i].tim;now--)
out_time(now);
}
ask[i].ans=ans;
}
} int main(){
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++){
scanf("%d",&val[i]);
}
block=sqrt(n);
for(int i=;i<=n;i++)
belong[i]=(i-)/block+;
char c;
int l,r;
for(int i=;i<=q;i++){
scanf(" %c",&c);
if(c=='Q'){
num1++;
scanf("%d%d",&ask[num1].L,&ask[num1].R);
ask[num1].id=num1;ask[num1].tim=num2;
}else{
num2++;
scanf("%d%d",&up[num2].p,&up[num2].v);
up[num2].z=;
}
}
sort(ask+,ask++num1);
solve();
sort(ask+,ask++num1,cmp);
for(int i=;i<=num1;i++)
printf("%d\n",ask[i].ans); return ;
}
【BZOJ 2120】数颜色【分块/莫队】的更多相关文章
- BZOJ 2120: 数颜色 分块
2120: 数颜色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php? ...
- Bzoj 2453: 维护队列 && Bzoj 2120: 数颜色 分块,bitset
2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 578 Solved: 247[Submit][Status][Discuss] ...
- BZOJ 2120 数颜色(带修改的莫队)
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MB Submit: 3478 Solved: 1342 [Submit][Status][Discus ...
- Bzoj 2120: 数颜色 && 2453: 维护队列 莫队,分块,bitset
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 2645 Solved: 1039[Submit][Status][Discuss] ...
- BZOJ 2120 数颜色 (带修莫队)
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 6367 Solved: 2537[Submit][Status][Discuss] ...
- BZOJ 2120 数颜色 【带修改莫队】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2120 2120: 数颜色 Time Limit: 6 Sec Memory Limit: ...
- BZOJ 2120: 数颜色
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 3623 Solved: 1396[Submit][Status][Discuss] ...
- bzoj 2120 数颜色 题解
转载请注明:http://blog.csdn.net/jiangshibiao/article/details/23990489 [原题] 2120: 数颜色 Time Limit: 6 Sec M ...
- bzoj 2120 数颜色 (带修莫队)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2120 题意:两种操作:Q 询问区间 l - r 内颜色的种类 ,R 单点修改 思路 ...
- BZOJ 2120 数颜色(带修改莫队)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2120 [题目大意] 给出一颜色序列,每次可以修改一个位置的颜色或者询问一个区间不同颜色 ...
随机推荐
- bzoj 3996 [TJOI2015]线性代数——最小割
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3996 b[ i ][ j ] 要计入贡献,当且仅当 a[ i ] = 1 , a[ j ] ...
- 读取设置config.ini配置
class CSenseIni { /************************************************************************/ /*写操作 * ...
- RK3288 USB UVC camera 摄像头 VIDIOC_DQBUF Failed!!! err[I/O error]
RK3288 Android5.1 多个品牌USB摄像头 同一块主板和代码,大部分品牌的USB摄像头可以正常使用,只有某一款USB摄像头不能使用. 插上摄像头,底层可以识别到摄像头. &l ...
- GNU Radio安装教程: Ubuntu14.04 + uhd3.10.0 + gnuradio3.7.10.1
1. 更新和安装依赖项 在编译安装uhd和gnuradio之前,确保已安装所需依赖项.Ubuntu系统运行: sudo apt-get update 安装UHD和GNURadio所需依赖项: On U ...
- 如何把SQLServer数据库从高版本降级到低版本
如何把SQLServer数据库从高版本降级到低版本 编写人:CC阿爸 2015-4-7 近期在给一个客户推行ECM系统时,基本客户的硬件环境,我们为其安装的为SQL2008 64位的数据库系统.在安装 ...
- POJ 3276 Face The Right Way(反转)
Face The Right Way Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6038 Accepted: 2 ...
- Java-Runoob-高级教程:Java 实例
ylbtech-Java-Runoob-高级教程:Java 实例 1.返回顶部 1. Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. ...
- 模拟admin组件自己开发stark组件之搜索和批量操作
搜索相关,搜索的本质就是从数据库查询出来的数据过滤 用户自定义给出过滤条件joker.py list_display = ('id','title','price',) show_add_btn = ...
- golang的吐槽
烂到极致的包管理:简单清晰的包管理机制是任何一门语言都需要具备的.后起之秀的golang,在众多成熟的其他语言包管理方式,居然做成这样,简直人间地狱.
- HDU2546题解
解题思路:先对价格排序(顺序或倒序都可以),然后,对前n-1(从1开始.排序方式为顺序)做容量为m(卡上余额)-5的01背包(背包体积和价值相等).假设dp[i][j]表示从前i个背包中挑选体积不超过 ...