【bzoj2453】维护队列

xiaoxiao2021-02-28  89

Description

你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。 Input

输入文件第一行包含两个整数N和M。 第二行N个整数,表示初始队列中弹珠的颜色。 接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹珠到第R个弹珠中,一共有多少不同颜色的弹珠,“R x c”表示A把x位置上的弹珠换成了c颜色。 Output

对于每个Q操作,输出一行表示询问结果。 Sample Input

2 3 1 2 Q 1 2 R 1 2 Q 1 2 Sample Output

2 1 HINT

对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。

题解

用pre[i]记录前一个和i相同颜色的球的所在位置 询问l到r时,如果pre[i]< l说明在l到r这一段没有和i颜色相同的球,则ans++ 然后分块 每一块内按pre[i]排序,二分即可。

代码

#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #define N 10001 #define M 1000001 using namespace std; int n,q,m,block; int c[N],pos[N],pre[N],b[N],last[M]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void reset(int x) { int l=(x-1)*block+1,r=min(x*block,n); for(int i=l;i<=r;i++)pre[i]=b[i]; sort(pre+l,pre+r+1); } void build() { for(int i=1;i<=n;i++) { b[i]=last[c[i]]; last[c[i]]=i; pos[i]=(i-1)/block+1; } for (int i=1;i<=m;i++)reset(i); } int find(int x,int v) { int l=(x-1)*block+1,r=min(x*block,n); int first=l; while(l<=r) { int mid=(l+r)>>1; if(pre[mid]<v)l=mid+1; else r=mid-1; } return l-first; } int ask(int x,int y) { int ans=0; if (pos[x]==pos[y]) { for (int i=x;i<=y;i++)if (b[i]<x) ans++; } else { for (int i=x;i<=block*pos[x];i++)if (b[i]<x) ans++; for (int i=block*(pos[y]-1)+1;i<=y;i++)if (b[i]<x) ans++; } for (int i=pos[x]+1;i<pos[y];i++) ans+=find(i,x); return ans; } void change(int x,int v) { for(int i=1;i<=n;i++)last[c[i]]=0; c[x]=v; for(int i=1;i<=n;i++) { int t=b[i]; b[i]=last[c[i]]; if(t!=b[i])reset(pos[i]); last[c[i]]=i; } } int main() { n=read();q=read(); for (int i=1;i<=n;i++) c[i]=read(); block=int(sqrt(n)+log(2*n)/log(2)); if(n%block)m=n/block+1; else m=n/block; build(); char ch[5];int x,y; for(int i=1;i<=q;i++) { scanf("%s",ch); x=read();y=read(); if(ch[0]=='Q')printf("%d\n",ask(x,y)); else change(x,y); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-75476.html

最新回复(0)