zoukankan      html  css  js  c++  java
  • Codeforces Round #426 (Div. 2)

      AB都是水题。

      C,设A和B是输入的最终分数,A和B一定具有这样的形式:A=a*b*b, B=a*a*b。那么A*B开三次方得到a*b,从而得到a和b,只要a和b存在答案便存在。开三次方使用二分即可。

      D题,题意是使序列刚好分成k段,每段的贡献值为这段不同数字的个数,问一种分法使得分数最大,求最大的分数。在扫描的过程中,假设当前出现的数字是now,last[now]表示的是now上次出现的位置(如果之前没出现,那么这个值为0)-->每次出现一个值,就使得[last[a[i]]+1, i]成段更新值+1,那么在 i 这个位置时,对于任意的 j ,[j, i]出现的不同的数字的个数是 j 这个位置的值。有了这个以后,考虑dp的转移,设dp[i][j]表示到 i 这个位置,使用了 j 段的最大答案,那么转移为:

      max{dp[o][k-1]+[o+1, j]的不同数字个数 | 1<=o<=i-1}

    对于一个位置 i ,利用前面所提的方法的话,是需要下一个位置的值c[i+1]和dp[i][k-1],这样暴力扫描的话转移复杂度是线性的,不能承受。如果能使得 i 和 i+1位置相同,那么便能使用一个值g[i] = c[i] + dp[i][k-1],之后再利用线段树查询区间g的最大值来更新当前的dp值了。因此考虑之前的方法更新位置错开一位,在[last[a[i]], i-1]的位置成段更新那么现在c[i]的值就表示之前c[i+1]的值了,然后转移dp并维护线段树中g的最大值即可。时间复杂度O(n*k*lg(n))。同时可以利用滚动数组压缩空间。具体见代码:

     1 #include <bits/stdc++.h>
     2 #define t_mid (l+r>>1)
     3 #define ls (o<<1)
     4 #define rs (o<<1|1)
     5 #define lson ls,l,t_mid
     6 #define rson rs,t_mid+1,r
     7 using namespace std;
     8 const int N = 35000 + 5;
     9 typedef long long ll;
    10 
    11 int n, k;
    12 int a[N];
    13 int last[N];
    14 int p[N];
    15 int dp[2][N];
    16 int c[N<<2], lazy[N<<2];
    17 void up(int o) {c[o] = max(c[ls], c[rs]);}
    18 void down(int o)
    19 {
    20     if(lazy[o])
    21     {
    22         c[ls] += lazy[o]; lazy[ls] += lazy[o];
    23         c[rs] += lazy[o]; lazy[rs] += lazy[o];
    24         lazy[o] = 0;
    25     }
    26 }
    27 void updateForSeg(int o,int l,int r,int ql,int qr,int dt)
    28 {
    29     if(l == ql && r == qr)
    30     {
    31         c[o] += dt;
    32         lazy[o] += dt;
    33         return ;
    34     }
    35     down(o);
    36     if(t_mid >= qr) updateForSeg(lson,ql,qr,dt);
    37     else if(ql > t_mid) updateForSeg(rson,ql,qr,dt);
    38     else
    39     {
    40         updateForSeg(lson,ql,t_mid,dt);
    41         updateForSeg(rson,t_mid+1,qr,dt);
    42     }
    43     up(o);
    44 }
    45 void updateForPt(int o,int l,int r,int pos,int dt)
    46 {
    47     if(l == r)
    48     {
    49         c[o] += dt;
    50         return ;
    51     }
    52     down(o);
    53     if(t_mid >= pos) updateForPt(lson,pos,dt);
    54     else updateForPt(rson,pos,dt);
    55     up(o);
    56 }
    57 int query(int o,int l,int r,int pos)
    58 {
    59     if(l == r) return c[o];
    60     down(o);
    61     if(pos <= t_mid) return query(lson,pos);
    62     else return query(rson,pos);
    63 }
    64 
    65 int main()
    66 {
    67     cin >> n >> k;
    68     for(int i=1;i<=n;i++)
    69     {
    70         scanf("%d",a+i);
    71         int now = a[i];
    72         p[i] = last[now];
    73         last[now] = i;
    74     }
    75     int now = 0, pre = 1;
    76     for(int i=1;i<=k;i++)
    77     {
    78         swap(now, pre);
    79         memset(c,0,sizeof c);
    80         memset(lazy,0,sizeof lazy);
    81         for(int j=1;j<=n;j++)
    82         {
    83             updateForSeg(1,0,n,p[j],j-1,1);
    84             updateForPt(1,0,n,j,dp[pre][j]);
    85             dp[now][j] = c[1];
    86         }
    87     }
    88     printf("%d
    ",dp[now][n]);
    89     return 0;
    90 }
    D

      

      

      

  • 相关阅读:
    搭建 mariadb 数据库主从同步
    MySQL--MVCC
    剑指 Offer 07. 重建二叉树
    剑指 Offer 06. 从尾到头打印链表
    MySQL--数据库范式
    剑指 Offer 05. 替换空格
    剑指 Offer 04. 二维数组中的查找
    剑指offer_03_数组中重复的数字(Java)
    Redis
    MySQL--SQL执行过程
  • 原文地址:https://www.cnblogs.com/zzyDS/p/7262129.html
Copyright © 2011-2022 走看看