2018.12.30【國家集訓隊】【洛谷P1903】數顏色 / 維護佇列(帶修莫隊)
阿新 • • 發佈:2019-01-01
傳送門
解析:
這道題好像以前在BZOJ上做過。
但是因為BZOJ資料較水,所以被我複雜度不對的程式碼搞過去了。。
真正的排序策略應該是這樣的:
塊大小設定成
左端點塊不同就按照左端點塊排序。
右端點塊不同根據左端點塊標號的奇偶性排序。
不然就按照時間戳的順序排個序。
每次暴力修改時間戳,然後調整塊的左右端點。
這樣複雜度才是真正的
證明自己用勢能分析一下就行了。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void outint(int a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
inline char getalpha(){
re char c;
while(!isalpha(c=gc()));
return c;
}
cs int N=100005,M=1000006;
int now,ans[N],l=1,r=0,cur;
int pre[N],pos[N],col[N],COL[N],cnt[M],tim[N];
int idxC,qcnt;
int B,block[N],bcnt;
struct Query{
int l,r,tim,id,pre;
friend bool operator<(cs Query &a,cs Query &b){
if(block[a.l]^block[b.l])return block[a.l]<block[b.l];
if(block[a.r]^block[b.r])return (block[a.l]&1)^(a.r>b.r);
return a.pre<b.pre;
}
}q[N];
inline void tim_r(int cur){
if(l<=pos[cur]&&pos[cur]<=r){
--cnt[COL[pos[cur]]];
if(!cnt[COL[pos[cur]]])--now;
}
pre[cur]=COL[pos[cur]];
COL[pos[cur]]=col[cur];
if(l<=pos[cur]&&pos[cur]<=r){
if(!cnt[COL[pos[cur]]])++now;
++cnt[COL[pos[cur]]];
}
}
inline void tim_l(int cur){
if(l<=pos[cur]&&pos[cur]<=r){
--cnt[COL[pos[cur]]];
if(!cnt[COL[pos[cur]]])--now;
}
COL[pos[cur]]=pre[cur];
if(l<=pos[cur]&&pos[cur]<=r){
if(!cnt[COL[pos[cur]]])++now;
++cnt[COL[pos[cur]]];
}
}
inline void tim_adjust(int now){
while(cur<idxC&&tim[cur+1]<=now)tim_r(++cur);
while(cur&&tim[cur]>now)tim_l(cur--);
}
inline void add(int pos){
if(!cnt[COL[pos]])++now;
++cnt[COL[pos]];
}
inline void del(int pos){
--cnt[COL[pos]];
if(!cnt[COL[pos]])--now;
}
int n,m;
signed main(){
n=getint();
m=getint();
B=pow(n,2.0/3.0);
bcnt=1;
for(int re i=1;i<=n;++i){
COL[i]=getint();
block[i]=bcnt;
if(i%B==0)++bcnt;
}
for(int re i=1;i<=m;++i){
switch(getalpha()){
case 'Q':{
q[++qcnt].id=qcnt;
q[qcnt].tim=i;
q[qcnt].l=getint();
q[qcnt].r=getint();
q[qcnt].pre=idxC;
break;
}
case 'R':{
tim[++idxC]=i;
pos[idxC]=getint();
col[idxC]=getint();
break;
}
}
}
sort(q+1,q+qcnt+1);
for(int re i=1;i<=qcnt;++i){
tim_adjust(q[i].tim);
while(r<q[i].r)add(++r);
while(l>q[i].l)add(--l);
while(r>q[i].r)del(r--);
while(l<q[i].l)del(l++);
ans[q[i].id]=now;
}
for(int re i=1;i<=qcnt;++i){
outint(ans[i]);
pc('\n');
}
return 0;
}