zoukankan      html  css  js  c++  java
  • [hdu] 5696 区间的价值 || 序列分治

    原题

    我们定义“区间的价值”为一段区间的最大值*最小值。
    一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。
    求长度分别为1~n的区间的最大价值。
    保证数据随机


    因为保证数据随机,所以我们可以考虑用区间的最大值把这个区间分为两个部分,这样答案的贡献就有两种情况。
    1、在同一个区间里
    2、跨过最大值,在两个区间里

    情况1通过递归就变成了情况2,而情况二我们通过two-points来完成。记录l指针和r指针,因为所求为最大值,所以选取l和r指针较大的内个加入,并每次更新答案即可。
    因为数据随机,所以O(nlogn)

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 100010
    typedef long long ll;
    using namespace std;
    ll n,ans[N],a[N];
    
    ll read()
    {
        ll ans=0,fu=1;
        char j=getchar();
        for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
        if (j=='-') j=getchar(),fu=-1;
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void solve(int l,int r)
    {
        if (l>r) return ;
        ll mx=0,pos,mn;
        for (int i=l;i<=r;i++)
    	if (a[i]>mx) mx=a[i],pos=i;
        int ll=pos-1,rr=pos+1;
        mn=mx;
        ans[1]=max(ans[1],mx*mx);
        while (ll>=l && rr<=r)
        {
    	if (a[ll]<a[rr]) mn=min(a[rr],mn),rr++;
    	else mn=min(a[ll],mn),ll--;
    	ans[rr-ll-1]=max(ans[rr-ll-1],mx*mn);
        }
        while (ll>=l) mn=min(a[ll],mn),ll--,ans[rr-ll-1]=max(ans[rr-ll-1],mx*mn);
        while (rr<=r) mn=min(a[rr],mn),rr++,ans[rr-ll-1]=max(ans[rr-ll-1],mx*mn);
        solve(l,pos-1);
        solve(pos+1,r);
    }
    
    int main()
    {
        while (~scanf("%lld",&n))
        {
    	memset(ans,0,sizeof(ans));
    	for (int i=1;i<=n;i++)
    	    a[i]=read();
    	solve(1,n);
    	for (int i=1;i<=n;i++)
    	    printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    初探webpack4--根据模版自动生成HTML
    初探webpack4---简介与常用loader使用方法
    axios请求五种方法
    iview实现国际化
    解决vuex页面刷新导致数据丢失问题
    一步一步搞懂支持向量机——从牧场物语到SVM(下)
    一步一步搞懂支持向量机——从牧场物语到SVM(上)
    set 利用lower_bound实现key索引
    unique & lower_bound C++
    逆元
  • 原文地址:https://www.cnblogs.com/mrha/p/8031212.html
Copyright © 2011-2022 走看看