洛谷 P1903 【模板】分块/带修改莫队

来源:互联网 发布:sql server时间戳转换 编辑:程序博客网 时间:2024/06/05 09:54

题目描述

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令:

1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第P支画笔替换为颜色Col。

为了满足墨墨的要求,你知道你需要干什么了吗?

输入输出格式

输入格式:
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。

第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。

第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

输出格式:
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

输入输出样例

输入样例#1:
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
输出样例#1:
4
4
3
4
说明

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

来源:bzoj2120

本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

还没学会莫队,用分块学的(蒟蒻的痛苦)

program df;
var i,j,n,m,x,y,z,k,t,s:longint;
a,b,c,d,ll,f,rr:array[0..1000000] of longint;
ss:string;
xx:char;
procedure sq(l,r:longint);
var i,j,mm,dd:longint;
begin
i:=l; j:=r;
mm:=f[(l+r) div 2];
repeat
while mm>f[i] do inc(i);
while f[j]>mm do dec(j);
if i<=j then
begin
dd:=f[i]; f[i]:=f[j]; f[j]:=dd;
inc(i); dec(j);
end;
until i>j;
if j>l then sq(l,j);
if r>i then sq(i,r);
end;

procedure deal(x:longint);
var l,r,i:longint;
begin
l:=c[x];
r:=d[x];
for i:=l to r do
f[i]:=ll[i];
sq(l,r);
end;

procedure change(x,y:longint);
var i,j,k:longint;
ff:boolean;
begin
for i:=1 to n do
rr[a[i]]:=0;
a[x]:=y;
for i:=1 to s do
begin
ff:=false;
for j:=c[i] to d[i] do
begin
k:=ll[j];
ll[j]:=rr[a[j]];
if ll[j]<>k then ff:=true;
rr[a[j]]:=j;
end;
if ff then deal(i);
end;
end;

function check(x,y:longint):longint;
var l,r,mid,k:longint;
begin
l:=c[x]; r:=d[x];
while l<=r do
begin
mid:=(l+r) div 2;
if y>f[mid] then l:=mid+1
else r:=mid-1;
end;
exit(l-c[x]);
end;

function search(x,y:longint):longint;
var i,j,k,l,r:longint;
begin
l:=(x-1) div t+1; r:=(y-1) div t+1; k:=0;
if (y-x)<(t<<1) then
begin
for i:=x to y do
if x>ll[i] then inc(k);
exit(k);
end;
if (x=c[l]) then dec(l);
if (y=d[r]) then inc(r);
for i:=x to d[l] do
if x>ll[i] then inc(k);
for i:=c[r] to y do
if x>ll[i] then inc(k);
for i:=l+1 to r-1 do
k:=k+check(i,x);
exit(k);
end;

begin
readln(n,m);
for i:=1 to n do
read(a[i]);
t:=trunc(sqrt(n));
k:=n div t;
if n mod k<>0 then inc(t);
s:=0;
for i:=1 to n do
if i mod t=1 then
begin
d[s]:=i-1;
inc(s);
c[s]:=i;
end;
d[s]:=n;
c[s+1]:=n+1;
d[s+1]:=n+1;

for i:=1 to n do
begin
ll[i]:=rr[a[i]];
rr[a[i]]:=i;
end;
for i:=1 to s do deal(i);
readln;
for i:=1 to m do
begin
readln(xx,x,y);
if xx=’Q’ then writeln(search(x,y))
else change(x,y);
end;

end.

原创粉丝点击