比如:我要求1~i区间内颜色数量=K的有多少个。
cnt[i]记录颜色数量
sum[cnt[i]]记录有颜色数量为cnt[i]的有多少个。
这里肯定不会直接问上述问题,但是复杂度的核心要考虑到这个问题。因为我自己笨老是想不到,记下来。
T1:cf_B2
这道题需要你对于i处理1~i区间颜色=k的有多少个。
这里不需要删除sum,也就是sum[1]会表示颜色种类,因为所有颜色会经过1。因为这里只需要考虑第一大和第二大的即可。
保证只有这两个。
T2:莫队求区间众数
这就需要放代码辣。
这里要删除sum,sum[cnt[i]]只能表示对应数目的有多少个,不过莫队删除添加都是比较方便的。
每加入一个,判断cnt是不是众数大,是的话记录。
要用到sum的是删除,删除的时候判断sum[最大]是否为1,为1的话众数需要往下推一格。[因为删除了一个众数3,导致3的数量减少,但sum[众数-1]+=1,所以必然有效。]
带离散化的处理多个询问区间众数代码:
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
#define maxn 2*100010
int n,m;
int A[maxn],num[maxn];
int ID[maxn],lsh[maxn];
int sum[maxn],ans[maxn];
int res=0;
struct node{
int l,r;
int index;
friend bool operator < (node a,node b){
if(ID[a.l]!=ID[b.l])return a.l<b.l;
else return a.r<b.r;
}
}Q[maxn];
void init(){
sort(lsh+1,lsh+n+1);
int cnt=unique(lsh+1,lsh+n+1)-lsh-1;
FOR(i,1,n){
A[i]=lower_bound(lsh+1,lsh+cnt+1,A[i])-lsh;
}
}
void del(int x){
if(sum[num[x]])sum[num[x]]--;
if(!sum[res])res=num[x]-1;
num[x]--;
sum[num[x]]++;
}
void add(int x){
if(sum[num[x]])sum[num[x]]--;
num[x]++;
sum[num[x]]++;
if(num[x]>res)res=num[x];
}
int main(){
cin>>n>>m;
int block = sqrt(n);
FOR(i,1,n){
scanf("%d",&A[i]);
lsh[i]=A[i];
ID[i]=(i-1)/block+1;
}
init();
FOR(i,1,m){
int x,y;
scanf("%d%d",&x,&y);
Q[i].l=x,Q[i].r=y;
Q[i].index=i;
}
sort(Q+1,Q+1+m);
int L=1,R=0;
FOR(i,1,m){
while(R<Q[i].r)add(A[++R]);
while(L>Q[i].l)add(A[--L]);
while(R>Q[i].r)del(A[R--]);
while(L<Q[i].l)del(A[L++]);
ans[Q[i].index]=res;
}
FOR(i,1,m)cout<<ans[i]<<endl;
}