【SDOI2008】郁闷的小J
Description
小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架。虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的。
具体说来,书架由N个书位组成,编号从1到N。每个书位放着一本书,每本书有一个特定的编码。
小J的工作有两类:
图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。
小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个书位组成,编号从1到N。每个书位放着一本书,每本书有一个特定的编码。
小J的工作有两类:
图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。
小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
……
你的任务是写一个程序来回答每个顾客的询问。
Input
第一行两个整数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的书共多少本。
接下来一行共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的书共多少本。
Output
对每一个顾客的查询,输出一个整数,表示顾客所要查询的结果。
Sample Input
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 2 3 4 5
Q 1 3 2
Q 1 3 1
C 2 1
Q 1 3 2
Q 1 3 1
Sample Output
1
1
0
2
1
0
2
Hint
【数据范围】
对于40%的数据,1<=N,M<=5000
对于100%的数据,1<=N,M<=100000
对于100%的数据,所有出现的书的编码为不大于2147483647的正数。
对于40%的数据,1<=N,M<=5000
对于100%的数据,1<=N,M<=100000
对于100%的数据,所有出现的书的编码为不大于2147483647的正数。
Solution
这道题似乎有显而易见的树套树做法
但是我们有更简单的做法
因为询问时只关心某一种书籍的个数,所以我们可以对每一种编号开一个能够维护区间和的数据结构即可
平衡树显然是可以做的,但是常数只能说差强人意
所以我们想到了线段树,只要动态开点就行了
顺带一提,这个编号的范围较大,需要离散
但是我们有更简单的做法
因为询问时只关心某一种书籍的个数,所以我们可以对每一种编号开一个能够维护区间和的数据结构即可
平衡树显然是可以做的,但是常数只能说差强人意
所以我们想到了线段树,只要动态开点就行了
顺带一提,这个编号的范围较大,需要离散
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define mid ((L+R)>>1)
using namespace std;
const int Maxn=200005;
inline int read(){
char c;int rec=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
return rec;
}
int cnt=0;
int n,m,ind,root[Maxn],c[Maxn];
struct Dynamic_Segment_Tree{int s[2],d;}tree[Maxn<<4];
inline void Infix(int &v,int L,int R,int p,int x){
if(!v)v=++ind;tree[v].d+=x;if(L==R)return ;
int f=(p>mid);f?L=mid+1:R=mid;Infix(tree[v].s[f],L,R,p,x);
}
inline int Ask(int v,int L,int R,int l,int r){
if(!v)return 0;if(L>r||R<l)return 0;
if(L>=l&&R<=r)return tree[v].d;
return Ask(tree[v].s[0],L,mid,l,r)+Ask(tree[v].s[1],mid+1,R,l,r);
}
map<int,int> table;
int main(){
n=read();m=read();char ch;
for(int i=1;i<=n;i++){c[i]=read();if(!table[c[i]])table[c[i]]=++cnt;}
for(int i=1;i<=n;i++)Infix(root[table[c[i]]],1,n,i,1);
while(m--){
while((ch=getchar())!='Q'&&ch!='C');
int x=read(),y=read();
if(ch=='Q')cout<<Ask(root[table[read()]],1,n,x,y)<<'\n';
else {
if(!table[y])table[y]=++cnt;
Infix(root[table[c[x]]],1,n,x,-1),Infix(root[table[c[x]=y]],1,n,x,1);
}
}
return 0;
}