POJ 2796 Feel Good 并查集

答案为0时要输出一个合理的区间...这是个坑.

-----------------------

const int maxn=110000;
const int maxm=10000;
int n;
int a[maxn];
struct Dat{
    int v;
    int idx;
};
bool cmp(const Dat& a,const Dat& b){
    return a.v>b.v;
}
Dat b[maxn];
int L[maxn],R[maxn],Mis[maxn];
int pa[maxn];
void makeset(int n){
    for (int i=0;i<=n;i++) pa[i]=i;
}
int findset(int x){
    if (x!=pa[x]) pa[x]=findset(pa[x]);
    return pa[x];
}
void unionset(int x,int y){
    x=findset(x);
    y=findset(y);
    if (x!=y){
        //cerr<<"union "<<x<<" "<<y<<endl;
        pa[x]=y;
        L[y]=min(L[x],L[y]);
        R[y]=max(R[x],R[y]);
        Mis[y]=min(Mis[x],Mis[y]);
        //cerr<<"now "<<L[y]<<" "<<R[y]<<" "<<Mis[y]<<endl<<endl;
    }
}
LL sum[maxn];
int main(){
    while (~scanf("%d",&n)){
        makeset(n);
        sum[0]=0;
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i].v=a[i];
            b[i].idx=i;
            L[i]=R[i]=i;
            Mis[i]=a[i];
            sum[i]=sum[i-1]+a[i];
        }
        sort(b+1,b+1+n,cmp);
        LL ans=0;
        int ansL=1,ansR=1;
        for (int i=1;i<=n;i++){
            //cerr<<b[i].v<<" "<<b[i].idx<<endl;
            if (b[i].idx>1&&b[i].v<=Mis[findset(b[i].idx-1)]){
                unionset(b[i].idx,b[i].idx-1);
            }
            if (b[i].idx<n&&b[i].v<=Mis[findset(b[i].idx+1)]){
                unionset(b[i].idx,b[i].idx+1);
            }
            int id=findset(b[i].idx);
            LL tmp=(LL)Mis[id]*(sum[R[id]]-sum[L[id]-1]);
            if (ans<tmp){
                ans=tmp;
                //cerr<<ans<<" "<<id<<" "<<Mis[id]<<" "<<R[id]<<" "<<L[id]<<endl;
                ansL=L[id];
                ansR=R[id];
            }
        }
        printf("%I64d
",ans);
        printf("%d %d
",ansL,ansR);
    }

	return 0;
}


-----------------------


原文地址:https://www.cnblogs.com/cyendra/p/3681538.html