列表

详情


NC26161. L. 最优子区间

描述

给长度为 n 的序列 a[],一个区间的得分为这个区间内有多少种元素恰出现一次。输出得分最大的区间,得分为多少。

输入描述

第 1 行,一个正整数,第 2 行 n 个正整数,第 i 个表示 

输出描述

输出一个正整数,表示答案。

示例1

输入:

5
1 2 1 2 3

输出:

3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 94ms, 内存消耗: 2912K, 提交时间: 2019-09-28 19:25:30

#include <cstdio>
using namespace std;

const int MAXN=1e5+5;
int seg[MAXN<<2],tag[MAXN<<2];
#define ls rt<<1
#define rs rt<<1|1

int tpr[MAXN],pre[MAXN];

void pushup(int rt){
    seg[rt]=seg[ls]>seg[rs]? seg[ls] : seg[rs];
}

void pushdown(int rt){
    if(tag[rt]){
        seg[ls]+=tag[rt];
        seg[rs]+=tag[rt];
        tag[ls]+=tag[rt];
        tag[rs]+=tag[rt];
        tag[rt]=0;
    }
}

void update(int L,int R,int v,int l,int r,int rt){
    if(L<=l && R>=r){
        seg[rt]+=v;
        tag[rt]+=v;
        return ;
    }
    int m=l+r>>1;
    pushdown(rt);
    if(L<=m) update(L,R,v,l,m,ls);
    if(R>m) update(L,R,v,m+1,r,rs);
    pushup(rt);
}

void chmax(int &a,int b){if(a<b) a=b;}

int main(){
    int n,x,ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        pre[i]=tpr[x];
        update(pre[i]+1,i,1,1,n,1);
        if(tpr[x]) update(pre[tpr[x]]+1,pre[i],-1,1,n,1);
        tpr[x]=i;
        chmax(ans,seg[1]);
    }
    printf("%d\n",ans);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 93ms, 内存消耗: 3192K, 提交时间: 2019-06-08 10:50:04

#include<iostream>
#include<cstdio>
using namespace std;int seg[400005],tag[400005],lst[100005],rem[100005];
inline void dt(int root) {
    if (!tag[root]) return;
    seg[root<<1]+=tag[root],seg[root<<1|1]+=tag[root];
    tag[root<<1]+=tag[root],tag[root<<1|1]+=tag[root];
    return tag[root]=0,void();
}
void mdf(int root,int l,int r,int ql,int qr,int delta) {int mid=l+r>>1;
    if (ql<=l&&r<=qr) return seg[root]+=delta,tag[root]+=delta,void();dt(root);
    if (ql<=mid) mdf(root<<1,l,mid,ql,qr,delta);
    if (qr>mid) mdf(root<<1|1,mid+1,r,ql,qr,delta);
    return seg[root]=max(seg[root<<1],seg[root<<1|1]),void();
}
int main() {int n,x,ans=0;
    scanf("%d",&n);for (register int i=1;i<=n;++i) {
        scanf("%d",&x),lst[i]=rem[x],mdf(1,1,n,lst[i]+1,i,1);
        if (lst[i]) mdf(1,1,n,lst[lst[i]]+1,lst[i],-1);
        rem[x]=i,ans=max(ans,seg[1]);
    }printf("%d",ans);return 0;
}

上一题