您的位置:首页 > 运维架构

【BZOJ】【2120】数颜色 & 【2453】维护队列

2015-06-15 16:37 423 查看

莫队算法

  分块大法吼

  这题乍一看跟HH的项链很像啊……只是多了一个修改操作……然而我就不会做了

/**************************************************************
Problem: 2120
User: Tunix
Language: C++
Result: Accepted
Time:536 ms
Memory:5636 kb
****************************************************************/

//BZOJ 2120
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=1,v=0; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
return r*v;
}
const int N=10010;
/*******************template********************/

int B,n,m,col
,blockid
;
struct ques{
int l,r,ti,num;
bool operator < (const ques &now)const {
if (blockid[l]==blockid[now.l]){
if (blockid[r]==blockid[now.r]) return ti<now.ti;
else return blockid[r]<blockid[now.r];
}else return blockid[l]<blockid[now.l];
}
}q
;
struct Time{
int x,y,pre;
}change
;

int pre
;

bool used
;
int ans=0,answer
,now;
int cnt[1000010];
/*********************var***********************/
inline void work(int x){
if (used[x]){
cnt[col[x]]--; if (cnt[col[x]]==0) ans--;
}else{
cnt[col[x]]++; if (cnt[col[x]]==1) ans++;
}
used[x]^=1;
}
inline void Change(int x,int y){
if (used[x]){work(x); col[x]=y; work(x);}
else col[x]=y;
}
inline void Timego(int tarti){
for(int i=now+1;i<=tarti;i++) Change(change[i].x,change[i].y);
for(int i=now;i>tarti;i--) Change(change[i].x,change[i].pre);
now=tarti;
}
/*********************func**********************/
int main(){
#ifndef ONLINE_JUDGE
freopen("2120.in","r",stdin);
freopen("2120.out","w",stdout);
#endif
n=getint(); m=getint();
B=pow(n,2.0/3.0);
F(i,1,n){
pre[i]=col[i]=getint();
blockid[i]=(i-1)/B+1;
}
char cmd[5];
int c1=0,c2=0;
F(i,1,m){
scanf("%s",cmd);
int x=getint(),y=getint();
if (cmd[0]=='Q'){
c2++;
q[c2]=(ques){x,y,c1,c2};
}else{
c1++;
change[c1]=(Time){x,y,pre[x]};
pre[x]=y;
}
}
sort(q+1,q+c2+1);
Timego(q[1].ti);
int l=q[1].l,r=q[1].r;
F(i,l,r) work(i);
answer[q[1].num]=ans;
F(i,2,c2){
Timego(q[i].ti);
F(j,min(l,q[i].l),max(l,q[i].l)-1) work(j);
l=q[i].l;
F(j,min(r,q[i].r)+1,max(r,q[i].r)) work(j);
r=q[i].r;
answer[q[i].num]=ans;
}
F(i,1,c2) printf("%d\n",answer[i]);
return 0;
}


View Code

2120: 数颜色

Time Limit: 6 Sec Memory Limit: 259 MB
Submit: 1832 Solved: 716
[Submit][Status][Discuss]

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。

Source

[Submit][Status][Discuss]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: