zoukankan      html  css  js  c++  java
  • 合并神犇

    题目背景

    loidc来到了NOI的赛场上,他在那里看到了好多神犇。

    题目描述

    神犇们现在正排成一排在刷题。每个神犇都有一个能力值p[i]。loidc认为坐在附近的金牌爷能力参差不齐非常难受。于是loidc便想方设法对神犇们进行人道主义合并。

    loidc想把神犇的能力值排列成从左到右单调不减。他每次可以选择一个神犇,把他合并到两侧相邻的神犇上。合并后的新神犇能力值是以前两位犇的能力值之和。每次合并完成后,被合并的两个神犇就会消失。合并后的新神犇不能再分开(万一他俩有女朋友咋办)因此每次合并后神犇的总数会减1.

    loidc想知道,想治好他的强迫症需要合并多少次

    输入输出格式

    输入格式:

    第一行一个整数 n。

    第二行 n 个整数,第 i 个整数表示 p[i]。

    输出格式:

    loidc需要合并的次数

    输入输出样例

    输入样例#1:
    8
    1 9 9 4 1 2 2 9
    输出样例#1:
    3

    说明

    对于 50%的数据,0< n <=5000。

    对于 100%的数据,0< n <=200000,0< p[i] <=2147483647,p 均为随机生成。

    n^2水过

    f[i]为第1~i位合并的次数

    pre[i]为第1~i位最末尾的数

    j为满足sum[i]-sum[j]>=pre[j]的最大数

    f[i]=f[j]+i-j-1

    pre[i]=sum[i]-sum[j]

    显然pre[i]越小越好,这样找到一个就可以退出

    正好数据很水

    复杂度强迫症硬是想nlogn可以套一个平衡树

    或者写一个二分

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int f[200001],n;
     7 long long sum[200001],pre[200001];
     8 int main()
     9 {int i,j;
    10   cin>>n;
    11   for (i=1;i<=n;i++)
    12     {
    13       scanf("%lld",&sum[i]);
    14       sum[i]+=sum[i-1];
    15     }
    16   for (i=1;i<=n;i++)
    17     {
    18       for (j=i-1;j>=0;j--)
    19     {
    20       if (sum[i]-sum[j]>=pre[j])
    21         break;
    22     }
    23       f[i]=f[j]+i-j-1;
    24       pre[i]=sum[i]-sum[j];
    25     }
    26   cout<<f[n];
    27 }

     这里附上单调队列的代码,由USACO干草堆改来

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long lol;
     7 lol sum[1000001],pre[1000001],f[1000001];
     8 int q[1000001],head,tail,n;
     9 int main()
    10 {int i;
    11   cin>>n;
    12   for (i=1;i<=n;i++)
    13     {
    14       scanf("%lld",&sum[i]);
    15       sum[i]+=sum[i-1];
    16     }
    17   head=0;tail=1;
    18   q[0]=0;
    19   for (i=1;i<=n;i++)
    20     {
    21       while (head+1<tail&&sum[i]>=sum[q[head+1]]+pre[q[head+1]]) head++;
    22       f[i]=f[q[head]]+1;
    23       pre[i]=sum[i]-sum[q[head]];
    24       //cout<<q[head]<<endl;
    25       while (head<tail&&sum[q[tail-1]]+pre[q[tail-1]]>sum[i]+pre[i]) tail--;
    26       q[tail++]=i;
    27     }
    28   cout<<n-f[n];
    29 }
  • 相关阅读:
    safari调试iphone
    git 本地仓库关联远程仓库
    video 自动播放及循环播放问题
    webpack4系列之【3. webpack4优化记录】
    展示博客
    第三天冲刺
    第二天冲刺
    第一天冲刺
    UML设计
    Alpha项目冲刺
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7489301.html
Copyright © 2011-2022 走看看