Educational Codeforces Round 55 E 分治
阿新 • • 發佈:2018-12-01
題意:一個數組,選一個連續區間[L,R] 使得 區間內相同的數 + 區間外a[i]=c的個數最多
思路:似乎可以o(n),這裡提供一個O(nogn)的分治方法,這類只選一個區間的問題很容易想到分治法,難在如何合併左右區間,這裡我們貪心合併即可,維護一下 左右可並的每種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; }