zoukankan      html  css  js  c++  java
  • Luogu P5504 [JSOI2011]柠檬

    题目
    首先我们容易想到,每一个连续段两端的颜色一定相同。
    预处理出(sum_i)表示(1sim i)中颜色为(a_i)的贝壳的个数。
    (f_i)为前(i)个贝壳的最大答案。
    那么容易写出转移方程(f_i=maxlimits_{jin[1,i]wedge a_i=a_j}(f_{j-1}+a_i(sum_i-sum_j+1)^2))
    这个东西显然可以斜率优化,每种颜色维护一个凸包即可。
    可以拆成这样
    (f_i=a_i(sum_i+1)^2+maxlimits_{jin[1,i]wedge a_i=a_j}((-2sum_i)(a_jsum_j)+(f_{j-1}+a_jsum_j^2-2a_jsum_j)))

    #include<bits/stdc++.h>
    #define ll long long
    #define ld long double
    #define pub push_back
    #define pob pop_back
    #define t1 s[id][s[id].size()-1]
    #define t2 s[id][s[id].size()-2]
    using namespace std;
    const int N=100007,M=10007;const ld eps=1e-8;
    int a[N],sum[N],pos[N];vector<int>s[N];ll x[N],y[N],f[N];
    int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
    ld slope(int i,int j){return (ld)(y[j]-y[i])/(x[j]-x[i]);}
    ll sqr(int x){return 1ll*x*x;}
    int main()
    {
        int n=read(),i,id;
        for(i=1;i<=n;++i) a[i]=read(),sum[i]=sum[pos[a[i]]]+1,pos[a[i]]=i;
        for(i=1;i<=n;++i) x[i]=1ll*sum[i]*a[i];
        for(i=1;i<=n;++i)
        {
    	id=a[i],y[i]=f[i-1]+1ll*a[i]*sum[i]*(sum[i]-2);
    	while(s[id].size()>=2&&slope(t2,t1)<=slope(t2,i)+eps) s[id].pob();
    	s[id].pub(i);
    	while(s[id].size()>=2&&slope(t2,t1)<=2.0*sum[i]+eps) s[id].pob();
    	f[i]=f[t1-1]+a[i]*sqr(sum[i]-sum[t1]+1);
        }
        return !printf("%lld",f[n]);
    }
    
  • 相关阅读:
    websocket使用nginx作为反向代理
    curl模拟http发送get或post接口测试
    linux tail -f messages查看控制台失败
    shell中使用>/dev/null 2>&1 丢弃信息
    mysql备份与还原
    计算机中RAM和ROM
    *C语言有关指针的变量声明中的几个易错点
    五种存储变量补充~作用域和存储时期
    typedef和#define的简单比较
    fopen()函数参数
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11761726.html
Copyright © 2011-2022 走看看