CF940F Machine Learning(一道带修莫队)蒟蒻第一次做带修莫队,觉得好简单
带修莫队,简单来讲有三个指针:L,R,time
然后进入奇异博士时刻!
带修莫队与普通莫队有什么不同呢?
时间指针又是啥?
所以如何转移时间指针?
所以我们可以写出时间转移函数
void RE(int pos,int val){
if(pos>=l&&pos<=r){
AC(col[pos],-1);
AC(val,1);
}
col[pos]=val;
}
只有当前修改操作在询问区间内时才进行修改。
其他都和普通莫队差不多。
分块方式从u=sqrt(n)变成了u=pow(n,0.666666)这点奇异博士也讲过了
找答案只用暴力就可以了。int id=1; while(happy[id]>0) id++; anw[s[i].Rk]=id;
完整代码…得问问奇异博士同不同意给
奇异博士说“OK”,那就给吧!
#include<bits/stdc++.h>
using namespace std;
const int N=500005;
struct Que{
int pos;
int old;
int now;
}t[N];
struct node{
int l,r;
int Rk;
int tim;
}s[N];
int n,m;
int col[N];
int now[N];
int b[N];
int u;
int l=1,r=0,T=0;
int Tm=0;
int ans=1;
int anw[N];
int happen[N]={0};
int happy[N]={0};
int cnt=0;
int hush[N];//这一位的离散化值
int domit[N];//domit[i]代表i的原值
map<int,int> e;//e[i]表示i对应的离散化值
int cnt1=0;
int cnt2=0;
bool cmp(node x,node y){
if(b[x.l]==b[y.l]){
if(b[x.r]==b[y.r]) return x.tim<y.tim;
return x.r<y.r;
}
return x.l<y.l;
}
void AC(int val,int dp){
happy[happen[val]]--;
happen[val]+=dp;
happy[happen[val]]++;
}
void RE(int pos,int val){
if(pos>=l&&pos<=r){
AC(col[pos],-1);
AC(val,1);
}
col[pos]=val;
}
int main(){
memset(happy,0,sizeof(happy));
happy[0]=2147483647;
scanf("%d%d",&n,&m);
u=pow(n,0.666666);
for(int i=1;i<=n;i++) b[i]=(i/u)+1;
for(int i=1;i<=n;i++){
scanf("%d",&col[i]);
if(e[col[i]]==0){
cnt++;
e[col[i]]=cnt;
}
col[i]=e[col[i]];
now[i]=col[i];
}
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==1){
cnt1++;
s[cnt1].l=b;
s[cnt1].r=c;
s[cnt1].Rk=cnt1;
s[cnt1].tim=Tm;
}
else{
cnt2++;
Tm++;
t[cnt2].pos=b;
t[cnt2].old=now[b];
if(e[c]==0) e[c]=++cnt;
t[cnt2].now=e[c];
now[b]=e[c];
}
}
sort(s+1,s+cnt1+1,cmp);
for(int i=1;i<=cnt1;i++){
while(l<s[i].l) AC(col[l],-1),l++;
while(l>s[i].l) l--,AC(col[l],1);
while(r<s[i].r) r++,AC(col[r],1);
while(r>s[i].r) AC(col[r],-1),r--;
while(T<s[i].tim) T++,RE(t[T].pos,t[T].now);
while(T>s[i].tim) RE(t[T].pos,t[T].old),T--;
int id=1;
while(happy[id]>0) id++;
anw[s[i].Rk]=id;
}
for(int i=1;i<=cnt1;i++) printf("%d\n",anw[i]);
return 0;
}