您的位置:首页 > 其它

[bzoj2120][数颜色] (暴力 or 分块)

2017-01-16 09:20 363 查看

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

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

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6


Sample Output

4
4
3
4


HINT

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

2016.3.2新加数据两组by Nano_Ape

Solution

先上简单的暴力,可以水过

#include <stdio.h>
#include <string.h>
#define M 1000010

inline int Rin() {
int x=0,c=getchar(),f=1;
for(; c<48||c>57; c=getchar())
if(c==45)f=-1;
for(; c>47&&c<58; c=getchar())
x=(x<<1)+(x<<3)+c-48;
return x*f; }

char c;
int g[M],n,m,a[M],top,x,y,i,mark[M],ans;

int main() {
n=Rin(),m=Rin();
for(i=1; i<=n; i++) {
a[i]=Rin();
if(!g[a[i]])
g[a[i]]=++top;
a[i]=g[a[i]]; }
while(m--) {
do c=getchar(); while(c!='Q'&&c!='R');
x=Rin(),y=Rin();
if(c=='Q') {
for(i=x,ans=0; i<=y; i++)
if(mark[a[i]]!=m)
mark[a[i]]=m,ans++;
printf("%d\n",ans);
}
else {
if(!g[y])g[y]=++top;
a[x]=g[y];
}
}
return 0;
}


一下是莫队的做法

otz menci

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 10010
#define M 1000010
#define RG register
#define inline __inline__ __attribute__((always_inline))

inline void Rin(RG int &x) {
x=0;RG int c=getchar(),f=1;
for(; c<48||c>57; c=getchar())
if(c==45)f=-1;
for(; c>47&&c<58; c=getchar())
x=(x<<1)+(x<<3)+c-48;
x*=f; }

int n,m,block_size,a
,utop,qtop,ans
,cnt[M];

struct Update {
int pos,eld,now; }U
;

struct Request{
int tim,l,r,id;

bool operator < (const Request &other)const {
if(l/block_size == other.l/block_size) {
if(r/block_size == other.r/block_size)
return tim < other.tim;
return r/block_size < other.r/block_size; }
return l/block_size < other.l/block_size; } }Q
;

inline void prepare() {
static int nowlist
;
memcpy(nowlist,a,sizeof a);
for(RG int i=1; i<=utop; i++) {
U[i].eld=nowlist[U[i].pos];
nowlist[U[i].pos]=U[i].now; } }

inline void extend(RG int &tmp,RG int pos,RG int dir) {
if(dir == 1) {
if(++cnt[a[pos]]==1)
tmp++; }
else
if(--cnt[a[pos]]==0)
tmp--; }

inline void modify(RG int &tmp,RG int T,RG int l,RG int r,RG int dir) {
RG Update x=U[T];
if(dir == 1) {
a[x.pos]=x.now;
if(x.pos >=l && x.pos <= r) {
if(--cnt[x.eld]==0)tmp--;
if(++cnt[x.now]==1)tmp++; } }
else {
if(x.pos >=l && x.pos <= r) {
if(--cnt[x.now]==0)tmp--;
if(++cnt[x.eld]==1)tmp++; }
a[x.pos]=x.eld; } }

inline void block_solve() {
for(RG int l=1,r=0,ans=0,T=0,i=1; i<=qtop; i++) {
while(r < Q[i].r)extend(ans,++r,1);
while(r > Q[i].r)extend(ans,r--,-1);

while(l > Q[i].l)extend(ans,--l,1);
while(l < Q[i].l)extend(ans,l++,-1);

while(T < Q[i].tim)modify(ans,++T,l,r,1);
while(T > Q[i].tim)modify(ans,T--,l,r,-1);
:: ans[Q[i].id]=ans; } }

int main() {

Rin(n),Rin(m);
for(RG int i=1; i<=n; i++)
Rin(a[i]);
for(RG int i=1; i<=m; i++) {
RG char c;
do c=getchar(); while(c != 'Q'&&c != 'R');
if(c == 'Q') {
++qtop;
Rin(Q[qtop].l),Rin(Q[qtop].r);
Q[qtop].id=qtop;
Q[qtop].tim=utop; }
else {
++utop;
Rin(U[utop].pos),Rin(U[utop].now); } }

prepare();
block_size=floor(pow(n,2.0/3)+1);
std::sort(Q+1,Q+1+qtop);
block_solve();

for(RG int i=1; i<=qtop;i++)
printf("%d\n",ans[i]);
return 0; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: