1. 程式人生 > >Increasing Frequency CodeForces - 1082E

Increasing Frequency CodeForces - 1082E

http://codeforces.com/contest/1082/problem/E

對每種顏色分開考慮 對第i種顏色 線上段樹對應點上更新為1 對第c種顏色 線上段樹對應點上更新為-1 求一下最大子段和 就是把第i種顏色變為第c種的增量 取個最大值即可

 

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
const int maxn=5e5+10;

struct node
{
    int sum,left,right,all;
};

vector <int> pre[maxn];
node tree[4*maxn];
int n,c;

void pushup(int cur)
{
    tree[cur].sum=tree[2*cur].sum+tree[2*cur+1].sum;
    tree[cur].left=max(tree[2*cur].left,tree[2*cur].sum+tree[2*cur+1].left);
    tree[cur].right=max(tree[2*cur+1].right,tree[2*cur+1].sum+tree[2*cur].right);
    tree[cur].all=max(max(tree[2*cur].all,tree[2*cur+1].all),tree[2*cur].right+tree[2*cur+1].left);
}

void update(int tar,int val,int l,int r,int cur)
{
    int m;
    if(l==r){
        tree[cur].sum=tree[cur].left=tree[cur].right=tree[cur].all=val;
        return;
    }
    m=(l+r)/2;
    if(tar<=m) update(tar,val,l,m,2*cur);
    else update(tar,val,m+1,r,2*cur+1);
    pushup(cur);
}

int main()
{
    int i,j,tmp,sum,ans,res;
    scanf("%d%d",&n,&c);
    sum=0;
    for(i=1;i<=n;i++){
        scanf("%d",&tmp);
        if(tmp==c){
            sum++;
            update(i,-1,1,n,1);
        }
        else pre[tmp].pb(i);
    }
    ans=sum;
    for(i=1;i<=500000;i++){
        if(i==c) continue;
        for(j=0;j<pre[i].size();j++){
            update(pre[i][j],1,1,n,1);
        }
        ans=max(ans,sum+tree[1].all);
        for(j=0;j<pre[i].size();j++){
            update(pre[i][j],0,1,n,1);
        }
    }
    printf("%d\n",ans);
    return 0;
}