题目
思路
首先如果q=0
那么显然是要把序列分成尽可能多的段,设每段众数的数量为Si,则ans=n-sigma(si)
考虑修改,可以用线段树维护
然后注意如何维护区间众数即可
代码
#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2e5+5;
struct TR{
int sum,l0,r0,nmin;
};
int n,q,a[maxn],maxa;
set<int> pos[maxn];
int nmax[4*maxn];
void nmax_xg(int k,int l,int r,int x,int z)
{
if (l==r)
{
nmax[k]+=z;
return;
}
int t=k<<1, mid=(l+r)>>1;
if (x<=mid) nmax_xg(t,l,mid,x,z); else nmax_xg(t+1,mid+1,r,x,z);
nmax[k]=max(nmax[t],nmax[t+1]);
}
int nmax_cx(int k,int l,int r,int x,int y)
{
if (x>y) return 0;
if (x<=l && r<=y) return nmax[k];
int t=k<<1, mid=(l+r)>>1, re=0;
if (x<=mid) re=max(re,nmax_cx(t,l,mid,x,y));
if (mid<y) re=max(re,nmax_cx(t+1,mid+1,r,x,y));
return re;
}
TR tr[4*maxn];
int bz[4*maxn];
void update(int k,int t)
{
tr[t].nmin+=bz[k], tr[t+1].nmin+=bz[k];
bz[t]+=bz[k], bz[t+1]+=bz[k];
bz[k]=0;
}
TR merge(const TR &a,const TR &b)
{
if (a.nmin<b.nmin) return a;
else if (a.nmin>b.nmin) return b;
else return (TR){a.sum+b.sum+nmax_cx(1,1,n,a.r0+1,b.l0),a.l0,b.r0,a.nmin};
}
void tr_js(int k,int l,int r)
{
if (l==r)
{
tr[k].l0=tr[k].r0=l;
return;
}
int t=k<<1, mid=(l+r)>>1;
tr_js(t,l,mid), tr_js(t+1,mid+1,r);
tr[k]=merge(tr[t],tr[t+1]);
}
void tr_xg_sing(int k,int l,int r,int x,int z)
{
if (l==r)
{
nmax_xg(1,1,n,x,z);
return;
}
int t=k<<1, mid=(l+r)>>1;
update(k,t);
if (x<=mid) tr_xg_sing(t,l,mid,x,z); else tr_xg_sing(t+1,mid+1,r,x,z);
tr[k]=merge(tr[t],tr[t+1]);
}
void tr_xg_q(int k,int l,int r,int x,int y,int z)
{
if (x>y) return;
if (x<=l && r<=y)
{
tr[k].nmin+=z;
bz[k]+=z;
return;
}
int t=k<<1, mid=(l+r)>>1;
update(k,t);
if (x<=mid) tr_xg_q(t,l,mid,x,y,z);
if (mid<y) tr_xg_q(t+1,mid+1,r,x,y,z);
tr[k]=merge(tr[t],tr[t+1]);
}
void modify(int x,int sig)
{
if (pos[x].empty()) return;
tr_xg_sing(1,0,n,*pos[x].begin(),sig*pos[x].size());
set<int>::iterator it=pos[x].end();
it--;
tr_xg_q(1,0,n,*pos[x].begin(),*it-1,sig);
}
void calc_ans()
{
int ans=n-tr[1].sum-nmax_cx(1,1,n,1,tr[1].l0)-nmax_cx(1,1,n,tr[1].r0+1,n);
printf("%d\n",ans);
}
int main()
{
scanf("%d %d",&n,&q);
fo(i,1,n)
{
scanf("%d",&a[i]);
maxa=max(maxa,a[i]);
pos[a[i]].insert(i);
}
tr_js(1,0,n);
fo(i,1,maxa) modify(i,1);
calc_ans();
while (q--)
{
int x,y;
scanf("%d %d",&x,&y);
modify(a[x],-1);
pos[a[x]].erase(x);
modify(a[x],1);
modify(y,-1);
pos[y].insert(x);
modify(y,1);
a[x]=y;
calc_ans();
}
}