题意:一个数组,选一个连续区间[L,R] 使得 区间内相同的数 + 区间外a[i]=c的个数最多
思路:似乎可以o(n),这里提供一个O(nogn)的分治方法,这类只选一个区间的问题很容易想到分治法,难在如何合并左右区间,这里我们贪心合并即可(枚举L,R的相同的数取什么),维护一下 左右可并的每种a[i] 的最优答案。可能表述不清,详细见代码。
代码:
#include<bits/stdc++.h>
#define PB push_back
#define X first
#define Y second
#define FIO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef double LD;
typedef pair<int,int> pii;
const int maxn=5e5+10;
const ll inf=1e9+7;
ll t,n,m,x,y,b,c;
int a[maxn];
struct P{
int c_cnt=0,res=0;
};
P ans[maxn*4];
int LM[maxn];
int Lbest[maxn],Rbest[maxn];
int solve(int L,int R,int rt,int flag){
int mid=(L+R)/2;
if(L==R){
ans[rt].c_cnt=(a[L]==c);
return ans[rt].res=1;
}
solve(L,mid,rt*2,2);
solve(mid+1,R,rt*2+1,1);
ans[rt].res=ans[rt*2].c_cnt+ans[rt*2+1].c_cnt;
ans[rt].res=max(ans[rt].res,ans[rt*2].res+ans[rt*2+1].c_cnt);
ans[rt].res=max(ans[rt].res,ans[rt*2+1].res+ans[rt*2].c_cnt);
ans[rt].c_cnt=ans[rt*2].c_cnt+ans[rt*2+1].c_cnt;
int tmpc=0;
for(int i=L;i<=R;++i)LM[a[i]]=Lbest[a[i]]=0;
for(int i=mid+1;i<=R;++i){
if(a[i]==c) tmpc++;
LM[a[i]]++;
if(LM[a[i]]+ans[rt*2+1].c_cnt-tmpc>Lbest[a[i]])
Lbest[a[i]]=LM[a[i]]+ans[rt*2+1].c_cnt-tmpc;
}
for(int i=L;i<=R;++i)LM[a[i]]=Rbest[a[i]]=0;
tmpc=0;
for(int i=mid;i>=L;--i){
if(a[i]==c) tmpc++;
LM[a[i]]++;
if(LM[a[i]]+ans[rt*2].c_cnt-tmpc>Rbest[a[i]]){
Rbest[a[i]]=LM[a[i]]+ans[rt*2].c_cnt-tmpc;
ans[rt].res=max(ans[rt].res,Rbest[a[i]]+Lbest[a[i]]);
}
}
return ans[rt].res;
}
int main(){
FIO;
cin>>n>>c;
for(int i=1;i<=n;i++)cin>>a[i];
cout<<solve(1,n,1,0)<<endl;
return 0;
}