题面
累了😰🤮不想搬了,就贴个链接好了
题解
当我们对某个区间进行操作过后,区间内只有一种值是有用的(成为众数的那个),所以,不妨就把操作定为将某个区间 [ l , r ] [l,r] [l,r] 中的所有 x x x 变为 y y y 。
某个数 y y y 可以输出,当且仅当存在 [ l , r ] , x [l,r],x [l,r],x 满足 [ l , r ] [l,r] [l,r] 内 x x x 的个数 加上 [ 1 , l ) ∪ ( r , n ] [1,l)\cup(r,n] [1,l)∪(r,n] 内 y y y 的个数等于众数出现次数的最大值。
因此我们对每个数值进行考虑。由于所有数的出现次数总和等于 n n n,出现次数大于等于 n \sqrt n n 的数值一定不超过 n \sqrt n n 个,我们可以对出现次数进行根号分治。
对于出现次数大于等于 n \sqrt n n 的数值 x x x,每一个都扫一遍序列,令 S x [ i ] S_x[i] Sx[i] 表示前 i i i 个位置出现 x x x 的次数,每个位置处理出 ( S a i [ i ] − S a i [ j ] ) + S x [ j ] (S_{a_i}[i]-S_{a_i}[j])+S_{x}[j] (Sai[i]−Sai[j])+Sx[j] 的最大值,再加上 i i i 后面的 x x x 出现次数,对 x x x 产生贡献。
对于出现次数小于 n \sqrt n n 的数值,会比较麻烦,但是由于最终必须要等于最大值才产生贡献,假设众数最大次数为 M M M ,我们就只需要考虑区间 [ l , r ] [l,r] [l,r] 中众数出现次数 ≥ M − n \geq M-\sqrt n ≥M−n 的情况。
我们从左往右扫 r r r ,令 L [ i ] L[i] L[i] 表示当前最大的 l l l 满足 [ l , r − 1 ] [l,r-1] [l,r−1] 的众数出现次数为 i i i 。每当扫到一个 r r r ,就只需要枚举与 a r a_r ar 同值的前 n \sqrt n n 个位置,来更新 L L L 数组。出现次数小于 n \sqrt n n 的 a r a_r ar,可以直接枚举完所有前面的同值位置 j j j,同时找到最大的 i i i 满足 L [ i ] > j L[i]>j L[i]>j ,用其更新 a r a_r ar 的答案。
时间复杂度 O ( T n n ) O(Tn\sqrt n) O(Tnn) 。
CODE
需要卡卡常
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma GCC optimize(2)
using namespace std;
#define MAXN 200005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define SQ 448
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
#define getchar() xchar()
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,s,o,k;
int ct[MAXN],CT[MAXN];
int a[MAXN],b[MAXN],id[MAXN],pr[MAXN],lst[MAXN];
int bu[MAXN][SQ+5],as[MAXN],bi[MAXN],rr[MAXN];
vector<int> vc[SQ+5];
inline int Max(int a,int b) {return a>b ? a:b;}
int main() {
freopen("mode.in","r",stdin);
freopen("mode.out","w",stdout);
int T = read();
while(T --) {
n = read();
map<int,int> mp;
for(int i = 1;i <= n;i ++) a[i] = read(),mp[a[i]] = 1,ct[i] = 0,lst[i] = 0;
int cn = 0;
for(auto i = mp.begin();i != mp.end();i ++) i->SE = ++ cn,id[cn] = i->FI;
for(int i = 1;i <= n;i ++) a[i] = mp[a[i]],ct[a[i]] ++;
m = 0;
for(int i = 1;i <= cn;i ++) {
CT[i] = ct[i]; as[i] = 0; bi[i] = 0;
if(ct[i] >= SQ) b[++ m] = i,bi[i] = m,vc[m].resize(CT[i]+2);
}
if(cn < SQ) {
for(int i = 1;i <= cn;i ++) {
if(!bi[i]) {
b[++ m] = i; bi[i] = m;
}
}
}
int ans = 0;
set<int> as2;
for(int i = 1;i <= m;i ++) {
int cal = CT[b[i]];
for(int j = 1;j <= n;j ++) ct[j] = 0;
int cnb = 0,mx = 0,mxa = cal;
for(int j = 1;j <= n;j ++) {
if(a[j] == b[i]) {
mxa = Max(mxa,mx + cal);
cnb ++; cal --;
}
else {
ct[a[j]] = Max(cnb + 1,ct[a[j]] + 1);
mx = Max(mx,ct[a[j]]);
}
}
mxa = Max(mxa,mx);
if(mxa > ans) {
ans = mxa;
as2.clear(); as2.insert(b[i]);
}
else if(mxa == ans) {
as2.insert(b[i]);
}
}
for(int i = 1;i <= n;i ++) ct[i] = 0,rr[i] = 0;
rr[0] = 0x3f3f3f3f;
int mm = 0;
if(cn > m) for(int i = 1;i <= n;i ++) {
ct[a[i]] ++; pr[i] = lst[a[i]]; lst[a[i]] = i;
if(bi[a[i]]) {
int x = bi[a[i]];
vc[x][ct[a[i]]] = i;
mm = max(ct[a[i]],mm);
for(int j = 1,k = ct[a[i]];k > 0 && k >= mm-SQ;j ++,k --) {
rr[k] = Max(rr[k],vc[x][j]);
}
}
else {
int p = i,nw = ct[a[i]] - 1,s2 = 0,s3 = max(0,mm-SQ),cal = CT[a[i]] - nw;
while(p) {
while(rr[s2+1] > pr[p]) s2 ++;
while(rr[s3+1] > pr[p]) s3 ++;
as[a[i]] = Max(as[a[i]],cal + nw + s2);
if(rr[s3] > pr[p]) as[a[i]] = Max(as[a[i]],cal + nw + s3);
p = pr[p]; nw --;
}
p = i; nw = 1;
while(p) {
rr[nw] = Max(rr[nw],p);
p = pr[p]; nw ++;
}
}
}
if(cn > m) for(int i = 1;i <= cn;i ++) {
if(!bi[i]) {
pr[n+1] = lst[i];
int p = n+1,nw = ct[i],s2 = 0,s3 = max(0,mm-SQ);
while(p) {
while(rr[s2+1] > pr[p]) s2 ++;
while(rr[s3+1] > pr[p]) s3 ++;
as[i] = Max(as[i],nw + s2);
if(rr[s3] > pr[p]) as[i] = Max(as[i],nw + s3);
p = pr[p]; nw --;
}
}
if(as[i] > ans) {
ans = as[i];
as2.clear(); as2.insert(i);
}
else if(as[i] == ans) {
as2.insert(i);
}
}
AIput(ans,'\n');
for(auto i = as2.begin();i != as2.end();i ++) {
AIput(id[*i],'\n');
}
}
return 0;
}