題解 P3709 【大爺的字串題】
阿新 • • 發佈:2020-08-22
Link
Solve
通過觀察我們發現,對於一列數,rp減小值就是眾數的個數,由於可以離線,我們就可以用莫隊來解決這個問題,每次幾下cntx,retx有點難理解,加入一個數的時候,用Ans刷cnt的max,刪除一個數時,判斷這個數是不是眾數,如果只有有且只有一個刪除的cnt而且刪除的是當前的眾數是,我們把Ans--,因為如果ret[cnt[x]-1]肯定不為0,可能是當前是這個數,也可能有好多個眾數,剩下的就是莫隊了。
Code
#include<bits/stdc++.h> using namespace std; const int maxn=200005; int n,m,cnt[maxn],a[maxn],block[maxn],ans[maxn],len,tot,now,ret[maxn]; struct AS{ int x,id; bool operator <(const AS B)const {return x<B.x;} }c[maxn]; struct BS{ int l,r,id; bool operator <(const BS B)const {return block[l]^block[B.l]?block[l]<block[B.l]:(block[l]&1)?r<B.r:r>B.r;} }q[maxn]; inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar(); return ret*f; } void inc(int x){ ret[cnt[x]]--; ret[++cnt[x]]++; now=max(now,cnt[x]); } void del(int x){ ret[cnt[x]]--; if(ret[cnt[x]]==0&&cnt[x]==now)now--; cnt[x]--; ret[cnt[x]]++; } int main(){ freopen("P3709.in","r",stdin); freopen("P3709.out","w",stdout); n=read();m=read();len=sqrt(n); for(int i=1;i<=n;i++)c[i].x=read(),c[i].id=i,block[i]=(i-1)/len+1; sort(c+1,c+1+n); a[c[1].id]=++tot; for(int i=2;i<=n;i++){ if(c[i].x!=c[i-1].x)tot++; a[c[i].id]=tot; } for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i; sort(q+1,q+1+m); int L=1,R=0; for(int i=1;i<=m;i++){ while(L<q[i].l)del(a[L++]); while(L>q[i].l)inc(a[--L]); while(R<q[i].r)inc(a[++R]); while(R>q[i].r)del(a[R--]); ans[q[i].id]=now; } for(int i=1;i<=m;i++)printf("%d\n",-ans[i]); return 0; }