zoukankan      html  css  js  c++  java
  • HGOI 20190709 题解

    Problem A 紫色激情

    一个序列${a_n}$,求出方差最大的子序列。

    其中方差 [l,r] 的定义是$S^2 = frac{1}{n} sumlimits_{i=l}^{r} (x_i-ar{x})^2$

    对于100%的数据满足$n leq 10^3$

    Sol : 直接推一波公式就可以前缀和优化了。

      ${ S_{l,r} }^2 = -ar{x}^2 +frac{sum_{i=l}^r {x_i}^2}{n}$

          时间复杂度$O(n^2)$

    # include<bits/stdc++.h>
    # define int long long
    using namespace std;
    const int N=2e3+10;
    int s1[N],s2[N];int n;
    inline int read()
    {
        int X=0,w=0; char c=0;
        while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
        while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
        return w?-X:X;
    }
    inline void write(int x)
    {
        if (x<0) x=-x,putchar('-'); 
        if (x>9) write(x/10);
        putchar(x%10+'0');
    }
    signed main()
    {
        n=read();
        for (int i=1;i<=n;i++) {
            int t=read(); 
            s1[i]=s1[i-1]+t;
            s2[i]=s2[i-1]+t*t;
        }
        double ans=-1e9; int ansl=0,ansr=0;
        for (int l=1;l<=n;l++)
         for (int r=l;r<=n;r++) {
          double t=-(double)(s1[r]-s1[l-1])*(s1[r]-s1[l-1])/(double)(r-l+1)/(double)(r-l+1);
          double w=(double)(s2[r]-s2[l-1])/(double)(r-l+1); 
          if (t+w>ans) { ans=t+w; ansl=l; ansr=r;}
        }
        write(ansl);putchar(' ');write(ansr); putchar('
    ');
        return 0;
    }
    passion.cpp

    Problem B 克罗地亚狂想曲

    共有$n$个节点,从每个节点可以向前面一个节点连一条边,而如果和后面一个节点的连边将被忽略。

    两个相连节点之间有一条连边,可以直接经过,找出一条访问的路径,使得每个节点被经过最多2次,

    经过路径上点值之和最大。

    对于100%的数据 , $n leq 3 imes 10^5 $

    Sol: 显然,向前连边的这个过程是没有后效性的,所以可以进行动态规划。

      而每个节点最多只能被经过2次保证了一次转移的合法性。

      设$f_i$表示走到节点$i$时候最大值。

      如果当前元素没有向前连边,那么答案就从上一节点走来,$f_i = f_{i-1} + a_i$

      如果当前元素有向前连边到$j$那么可以考虑从$j$过来在经过$j$,在走到$i$,再接下去走。

      这等价于$j->i$的路径被累加了$2$次,那么转移方程就是$f_i = f_{j-1}  + 2 sumlimits_{k=j}^{i} a_k$

      然后那个$sum$累加可以用前缀和优化掉,这样这个DP就是线性的了。

      复杂度$O(n)$

    # include <bits/stdc++.h>
    # define int long long
    using namespace std;
    const int N=3e5+10;
    int from[N],f[N],s[N],n;
    inline int read()
    {
        int X=0,w=0; char c=0;
        while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
        while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
        return w?-X:X;
    }
    inline void write(int x)
    {
        if (x<0) x=-x,putchar('-'); 
        if (x>9) write(x/10);
        putchar(x%10+'0');
    }
    signed main()
    {
        n=read();
        for (int i=1;i<=n;i++) {
            int t=read();
            if (t>i) continue;
            from[i]=t;
        }
        for (int i=1;i<=n;i++) {
            int t=read();
            s[i]=s[i-1]+t;
        }
        for (int i=1;i<=n;i++) {
            f[i]=f[i-1]+s[i]-s[i-1];
            if (from[i]!=0) f[i]=max(f[from[i]-1]+2*(s[i]-s[from[i]-1]),f[i]);
        }
        write(f[n]);putchar('
    '); 
        return 0;
    }
    rhapsody.cpp

    Problem C 花之舞

    给出一个字符串中,求该字符串中最大不重复双倍回文串覆盖。

    对于100%的数据,$ len(s) leq 10^3 $ 

    Sol :  首先我们可以通过字符串Hash的做法判定一个串是不是回文串,这样只需要一遍$O(n)$的预处理,再$O(1)$判定即可。

    然后我们可以$O(n^2)$枚举从$i$开始的所有双倍回文串,然后可以使用类似线段覆盖的DP做出最大不重复双倍回文串覆盖。

    最终的复杂度是$O(n^2)$的。

    # include<bits/stdc++.h>
    # define int long long
    using namespace std;
    const int mo=1e9+7;
    const int base=131;
    const int N=1e3+10;
    int p[N],a[N],hash1[N],hash2[N],f[N];
    int n;
    vector<int>v[N];
    inline int read()
    {
        int X=0,w=0; char c=0;
        while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
        while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
        return w?-X:X;
    }
    inline void write(int x)
    {
        if (x<0) x=-x,putchar('-'); 
        if (x>9) write(x/10);
        putchar(x%10+'0');
    }
    int gethash(int num,int l,int r)
    {
        if (num==1) return ((hash1[r]-hash1[l-1]*p[r-l+1]%mo)%mo+mo)%mo;
        else return ((hash2[r]-hash2[l-1]*p[r-l+1]%mo)%mo+mo)%mo;
    }
    bool check(int l,int r)
    {
        if ((r-l+1)&1) {
            int pos=(l+r)/2,len=(r-l)/2;        
            if (gethash(1,pos,pos+len)==gethash(2,n+1-pos,n+1-pos+len)) return 1;
            else return 0;
        } else {
            int pos1=(l+r)/2,pos2=pos1+1,len=(r-l-1)/2;
            if (gethash(1,pos2,pos2+len)==gethash(2,n+1-pos1,n+1-pos1+len)) return 1;
            else return 0;
        }
    }
    void fun(int pos)
    {
        for (int mid=(n+1-pos)/2;mid>=1;mid--) 
         if (check(pos,pos+mid-1)&&check(pos+mid,pos+2*mid-1)&&gethash(1,pos,pos+mid-1)==gethash(1,pos+mid,pos+2*mid-1)) 
             v[pos].push_back(pos+2*mid-1);
    }
    signed main()
    {
    //    freopen("dance.in","r",stdin);
    //    freopen("dance.out","w",stdout);
        n=read(); p[0]=1;
        for (int i=1;i<=n;i++) 
            a[i]=read(),p[i]=p[i-1]*base%mo;    
        for (int i=1;i<=n;i++) 
            hash1[i]=(hash1[i-1]*base%mo+a[i])%mo;
        int u=0;    
        for (int i=n;i>=1;i--) u++,hash2[u]=(hash2[u-1]*base%mo+a[i])%mo;
        for (int i=1;i<=n;i++) fun(i); 
        for (int i=n;i>=1;i--) {
             f[i]=f[i+1];
             for (int j=0;j<v[i].size();j++)
              f[i]=max(f[i],f[v[i][j]+1]+(v[i][j]-i+1));
         }
        write(f[1]); putchar('
    ');
        return 0;
    } 
    dance.cpp
  • 相关阅读:
    JBoss+Ant实现EJB无状态会话bean实例
    Nginx简单介绍
    SVN版本号管理工具使用中常见的代码提交冲突问题的解决方法
    深入分析Java中的I/O类的特征及适用场合
    ZOJ 3689 Digging(贪心+dp)
    uva 10641 (来当雷锋的这回....)
    Java编程中“为了性能”尽量要做到的一些地方
    wikioi 1306 机智Trie树
    PE文件结构(三) 输入表
    初始化的数值(int、double等)(一)
  • 原文地址:https://www.cnblogs.com/ljc20020730/p/11156950.html
Copyright © 2011-2022 走看看