[BZOJ2792][Poi2012]Well

2792: [Poi2012]Well

Time Limit: 40 Sec  Memory Limit: 64 MB
Submit: 137  Solved: 61
[Submit][Status][Discuss]

Description

给出n个正整数X1,X2,...Xn,可以进行不超过m次操作,每次操作选择一个非零的Xi,并将它减一。

最终要求存在某个k满足Xk=0,并且z=max{|Xi - Xi+1|}最小。

输出最小的z和此时最小的k。

Input

第一行两个正整数n, m (1<=n<=1,000,000, 1<=m<=10^18)。第二行n个正整数X1,X2,...Xn (Xi<=10^9)。

Output

输出k和z。数据保证方案一定存在。

Sample Input

16 15
8 7 6 5 5 5 5 5 6 6 7 8 9 7 5 5

Sample Output

1 2

HINT

将X序列变为

0 2 4 5 5 5 5 5 6 6 7 8 9 7 5 5

此时k=1,z=2,共操作了8+5+2=15次。

Source

鸣谢 oimaster

[Submit][Status][Discuss]

要求最小化最大值,肯定想到二分。

二分判定的难点在于如何求最小的能等于0的数。

假如要把i位置变成0,则一定会修改一个区间[L,R]

所以必须满足a[L]>(i-L)*mid,且a[R]>(R-i)*mid

这两个显然都是单调的,然后[L,R]这个区间要想修改最小的话,最后一定变成前后两个等差数列,其中公差=mid,第i项=0,直接统计答案即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define N 1000010
 4 #define mid (l+r>>1)
 5 #define ll long long
 6 using namespace std;
 7 int n,a[N],b[N];
 8 ll m,f[N],sum[N];
 9 inline int check(int x)
10 {
11     ll ans=0;
12     for(int i=1;i<=n;i++)b[i]=a[i];
13     for(int i=2;i<=n;i++)
14     if(b[i]-b[i-1]>x)
15     ans+=b[i]-b[i-1]-x,b[i]=b[i-1]+x;
16     for(int i=n-1;i;i--)
17     if(b[i]-b[i+1]>x)
18     ans+=b[i]-b[i+1]-x,b[i]=b[i+1]+x;
19     for(int i=1;i<=n;i++)
20     sum[i]=sum[i-1]+b[i];
21     if(ans>m)return 0;
22     for(int i=1,j=1;i<=n;i++)
23     {
24         while(j<i&&b[j]<=(ll)(i-j)*x)j++;
25         f[i]=sum[i-1]-sum[j-1]-(ll)(i-j)*(i-j+1)/2*x;
26     }
27     for(int i=n,j=n;i;i--)
28     {
29         while(j>i&&b[j]<=(ll)(j-i)*x)j--;
30         f[i]+=sum[j]-sum[i]-(ll)(j-i)*(j-i+1)/2*x;
31     }
32     for(int i=1;i<=n;i++)
33     if(b[i]+f[i]+ans<=m)return i;
34     return 0;
35 }
36 int main()
37 {
38     int l=0,r=0,ans=0;
39     scanf("%d%lld",&n,&m);
40     for(int i=1;i<=n;i++)
41     scanf("%d",&a[i]),r=max(r,a[i]);
42     while(l<=r)
43     {
44         if(check(mid))ans=mid,r=mid-1;
45         else l=mid+1;
46     }
47     printf("%d %d",check(ans),ans);
48 }

时间: 2024-10-21 15:37:03

[BZOJ2792][Poi2012]Well的相关文章

Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 278  Solved: 185[Submit][Status][Discuss] Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度

[BZOJ2797][Poi2012]Squarks

2797: [Poi2012]Squarks Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 211  Solved: 89[Submit][Status][Discuss] Description 设有n个互不相同的正整数{X1,X2,...Xn},任取两个Xi,Xj(i≠j),能算出Xi+Xj.现在所有取法共n*(n-1)/2个和,要你求出X1,X2,...Xn. Input 第一行一个正整数n (3<=n<=300).第二行n*(n-1)/2

[BZOJ2791][Poi2012]Rendezvous

2791: [Poi2012]Rendezvous Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 95  Solved: 71[Submit][Status][Discuss] Description 给定一个n个顶点的有向图,每个顶点有且仅有一条出边.对于顶点i,记它的出边为(i, a[i]).再给出q组询问,每组询问由两个顶点a.b组成,要求输出满足下面条件的x.y:1. 从顶点a沿着出边走x步和从顶点b沿着出边走y步后到达的顶点相同.2.

[BZOJ2793][Poi2012]Vouchers

2793: [Poi2012]Vouchers Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 316  Solved: 148[Submit][Status][Discuss] Description 考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个.正整数中有m个数被标成了幸运数,问有哪些人取到了幸运数. Input 第一行一个正整数m (m<=1,000,000),下面m行每行一

[BZOJ2795][Poi2012]A Horrible Poem

2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 261  Solved: 150[Submit][Status][Discuss] Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. Input 第一行一个正整数n (n<=500,000),表示S的长度.第二行n个小

[BZOJ2788][Poi2012]Festival

2788: [Poi2012]Festival Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 187  Solved: 91[Submit][Status][Discuss] Description 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1. 给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb 2. 给出c,d (1<=c,d<=n),要求满足Xc <= Xd 在满足所

[BZOJ2790][Poi2012]Distance

2790: [Poi2012]Distance Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 225  Solved: 115[Submit][Status][Discuss] Description 对于两个正整数a.b,这样定义函数d(a,b):每次操作可以选择一个质数p,将a变成a*p或a/p, 如果选择变成a/p就要保证p是a的约数,d(a,b)表示将a变成b所需的最少操作次数.例如d(69,42)=3. 现在给出n个正整数A1,A2,.

2795: [Poi2012]A Horrible Poem

2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 484  Solved: 235[Submit][Status][Discuss] Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. Input 第一行一个正整数n (n<=500,000),表示S的长度.第二行n个小

【BZOJ2789】[Poi2012]Letters 树状数组

[BZOJ2789][Poi2012]Letters Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度. 第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母. Output 一个非负整数,表示最少的交换次数. Sample Input 3 ABC BCA Samp