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

bzoj2453 维护队列 & bzoj2120 数颜色 (带修改莫队)

2017-11-26 11:01 316 查看

bzoj2453 维护队列 & bzoj2120 数颜色

原题地址

http://www.lydsy.com/JudgeOnline/problem.php?id=2453

http://www.lydsy.com/JudgeOnline/problem.php?id=2120

题意:

小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。

小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。

A有时候会依据个人喜好,替换队列中某个弹珠的颜色。

数据范围

1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。

题解:

带修改莫队裸题。

相比不带修多了一维时间(在第几个修改之后)。

块大小n23,块个数n13

排序按照 L所在快,R所在块,时间(在第几个修改之后) 排序。

复杂度证明:

左指针移动:n次*n23的距离=O(n∗n23)= O(n53)

右指针移动:n次 * n23的距离+n13次 * n23的距离= O(n∗n23+n13∗n)= O(n53)

时间指针移动:(n13)2次 * n的距离=O((n13)2∗n)= O(n53)

于是复杂度 O(n53)

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=10000;
struct query
{
int l,r,t,id;
}Q
;
struct modify
{
int pos,pre,nxt;
}M
;
int n,m,col
,st
,ans
,block,ret=0,qs,md,cnt[1000006];
int blo(int x)
{
return(x-1)/block+1;
}
bool cmp(const query &A,const query &B)
{
if(blo(A.l)!=blo(B.l)) return A.l<B.l;
else if(blo(A.r)!=blo(B.r)) return A.r<B.r;
else return A.t<B.t;
}
void add(int x) {x=col[x]; if(!cnt[x]) ret++; cnt[x]++;}
void erase(int x) {x=col[x]; cnt[x]--; if(cnt[x]==0)  ret--;}
void change(int tim,int l,int r,int opt)
{
int pos=M[tim].pos; int pre=M[tim].pre; int now=M[tim].nxt;
if(pos>=l&&pos<=r) erase(pos);
col[pos]=(opt>0)? now:pre;
if(pos>=l&&pos<=r) add(pos);
}
void moto()
{
int lf=1; int rg=0; int cur=0; ret=0;
for(int i=1;i<=qs;i++)
{
while(rg<Q[i].r) add(++rg);
while(lf>Q[i].l) add(--lf);
while(lf<Q[i].l) erase(lf++);
while(rg>Q[i].r) erase(rg--);
while(cur<Q[i].t) change(++cur,Q[i].l,Q[i].r,1);
while(cur>Q[i].t) change(cur--,Q[i].l,Q[i].r,-1);
ans[Q[i].id]=ret;
}

}
int main()
{
scanf("%d%d",&n,&m);
block=sqrt(n);
for(int i=1;i<=n;i++) {scanf("%d",&col[i]);st[i]=col[i];}
qs=0,md=0;
for(int i=1;i<=m;i++)
{
char opt[5]; int x,y;
scanf("%s",opt); scanf("%d%d",&x,&y);
if(opt[0]=='Q')
{
Q[++qs].l=x;Q[qs].r=y; Q[qs].t=md; Q[qs].id=qs;
}
else
{
M[++md].pos=x; M[md].pre=col[x]; M[md].nxt=y; col[x]=y;
}
}
for(int i=1;i<=n;i++) col[i]=st[i];
sort(Q+1,Q+qs+1,cmp);
moto();
for(int i=1;i<=qs;i++)
printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: