Educational Codeforces Round 55 E 分治

题意:一个数组,选一个连续区间[L,R] 使得 区间内相同的数 + 区间外a[i]=c的个数最多

思路:似乎可以o(n),这里提供一个O(nogn)的分治方法,这类只选一个区间的问题很容易想到分治法,难在如何合并左右区间,这里我们贪心合并即可,维护一下 左右可并的每种a[i] 的最优答案。可能表述不清,详细见代码。

代码:

#include
#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 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<

 

你可能感兴趣的:(贪心,分块)