[SDOI2008]郁闷的小J

题目描述

小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架。虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的。

具体说来,书架由N个书位组成,编号从1到N。每个书位放着一本书,每本书有一个特定的编码。

小J的工作有两类:

1.图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。

2.小J需要回答顾客的查询,顾客会询问某一段连续的书位中某一特定编码的书有多少本。

例如,共5个书位,开始时书位上的书编码为1,2,3,4,5

一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:1

一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:1

此时,图书馆购进一本编码为“1”的书,并将它放到2号书位。

一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:0

一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:2

……

你的任务是写一个程序来回答每个顾客的询问。

输入输出格式

输入格式:

第一行两个整数N,M,表示一共N个书位,M个操作。

接下来一行共N个整数数A1,A2…AN,Ai表示开始时位置i上的书的编码。

接下来M行,每行表示一次操作,每行开头一个字符

若字符为‘C’,表示图书馆购进新书,后接两个整数A(1<=A<=N),P,表示这本书被放在位置A上,以及这本书的编码为P。

若字符为‘Q’,表示一个顾客的查询,后接三个整数A,B,K(1<=A<=B<=N),表示查询从第A书位到第B书位(包含A和B)中编码为K的书共多少本。

输出格式:

对每一个顾客的查询,输出一个整数,表示顾客所要查询的结果。

输入输出样例

输入样例#1: 复制

5 5

1 2 3 4 5

Q 1 3 2

Q 1 3 1

C 2 1

Q 1 3 2

Q 1 3 1

输出样例#1: 复制

1

1

0

2

说明

对于40%的数据,1<=N,M<=5000

对于100%的数据,1<=N,M<=100000

对于100%的数据,所有出现的书的编码为不大于2147483647的正数。

题解

一眼看上去。

分块啊!

点开标签,平衡树???

平衡树打得少告辞。

还是用分块水一下吧。

这个题目类似于教主的魔法。

我们只需要把每一个块排一遍序。

然后编号嘛。就是二分一下就好了。

每次查询一下\(O(logn \sqrt n)\)再乘上个\(m\)就可以了。

要吸氧,可能是我分块打得太垃圾了吧。

不吸只有四十分。

代码

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1000001;
int bl[N],l[N],r[N];
int a[N],ch[N];
int n,m,k,tmp;
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
} void build(){
for(int i=1;i<=tmp;i++)
l[i]=(i-1)*tmp+1,r[i]=i*tmp;
for(int i=1;i<=n;i++)bl[i]=(i-1)/tmp+1;
if(r[tmp]<n){
tmp++,r[tmp]=n,l[tmp]=r[tmp-1]+1;
for(int i=l[tmp];i<=n;i++)bl[i]=tmp;
}
for(int i=1;i<=tmp;i++){
sort(a+l[i],a+r[i]+1);
}
} void change(int x,int y){
ch[x]=y;
for(int i=l[bl[x]];i<=r[bl[x]];i++)a[i]=ch[i];
sort(a+l[bl[x]],a+r[bl[x]]+1);
} int query(int ll,int rr,int v){
int ans=0;
if(bl[ll]==bl[rr]){
for(int i=ll;i<=rr;i++)if(ch[i]==v)ans++;
return ans;
}
for(int i=bl[ll]+1;i<=bl[rr]-1;i++){
int lv=lower_bound(a+l[i],a+r[i]+1,v)-a;
int rv=lower_bound(a+l[i],a+r[i]+1,v+1)-a-1;
ans+=rv-lv+1;
}
for(int i=ll;i<=r[bl[ll]];i++)
if(ch[i]==v)ans++;
for(int i=l[bl[rr]];i<=rr;i++)
if(ch[i]==v)ans++;
return ans;
} int main(){
n=read();m=read();tmp=sqrt(n);
for(int i=1;i<=n;i++){
a[i]=ch[i]=read();
}
build();
while(m--){
char opt;
scanf("%s",&opt);
if(opt=='C'){
int x=read(),y=read();
change(x,y);
}
if(opt=='Q'){
int ll=read(),rr=read(),v=read();
printf("%d\n",query(ll,rr,v));
}
}
return 0;
}

最新文章

  1. CentOS7 FTP服务搭建(虚拟用户访问FTP服务)
  2. Web.config自定义节点configSections
  3. ServletContextListener使用详解
  4. 快速传输大数据(tar+lz4+pv)
  5. 1 2 3 n
  6. Hbase原理
  7. linux echo命令的-n、-e两个参数
  8. Joy of Programming: Understanding Bit-fields in C
  9. Wiz开发 定时器的使用与处理
  10. Linux操作系统是如何工作的?破解操作系统的奥秘
  11. UGUI 下拉滚动框
  12. 判断两个View的GRect是否相等
  13. win7笔记本电脑实现wifi共享
  14. Lak3 Counting(POJ No.2386)
  15. linux命令英文缩写的含义(方便记忆)
  16. element-ui更换主题色
  17. Python练手例子(15)
  18. [Swift]LeetCode720. 词典中最长的单词 | Longest Word in Dictionary
  19. java遍历List中的map的几种方法
  20. java虚拟机的学习书籍推荐

热门文章

  1. npx命令
  2. laravel报错:Unable to detect application namespace.
  3. BZOJ 4026 dC Loves Number Theory (主席树+数论+欧拉函数)
  4. js 事件监听,执行某操作
  5. promise的原理
  6. ANY和ALL
  7. 在Html5中与服务器交互
  8. jquery在文本框之后添加红*
  9. 阅读《Android 从入门到精通》(15)——数字时钟
  10. map和multimap映射容器