• Codeforces Round #802 (Div. 2) C D


    传送门:
    C. Helping the Nature

    D. River Locks

    C题意:给你一个序列a,你可以使用以下三个操作:
    操作一:对于区间[1,i] - 1

    操作二:对于区间[i,n] - 1

    操作三:对于区间[1,n] + 1

    求最小操作次数使得a序列全为0。

    C分析:观察操作的本质:
    操作一:使得差分d[i+1]+1

    操作二:使得差分d[i]-1

    操作三:操作三

    O(n)铺平之后(所有数字都一样了)再加上a序列的一个数字即可。

    C代码:
     

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. #define int long long
    4. const int maxn=1e6+5;
    5. int a[maxn],d[maxn];
    6. void solve()
    7. {
    8. int n;
    9. cin>>n;
    10. for(int i=1;i<=n;i++)
    11. {
    12. cin>>a[i];
    13. d[i]=a[i]-a[i-1];
    14. }
    15. int cnt=0;
    16. int a1=a[1];
    17. for(int i=2;i<=n;i++)
    18. {
    19. cnt+=abs(d[i]);
    20. if(d[i]<0)
    21. {
    22. a1+=d[i];
    23. }
    24. }
    25. cnt+=abs(a1);
    26. cout<<cnt<<endl;
    27. }
    28. signed main()
    29. {
    30. ios::sync_with_stdio(0);
    31. int t=1;
    32. cin>>t;
    33. while(t--) solve();
    34. }

    D题意:有n个水库,每个水库的容量为v[i],且有一个水管连接,水管打开后每秒会流入1升的水。注意每个水库还连接着下一个水库,当第i个水库满了之后,溢出的水会流到第i+1个水库中。

    你需要回答q次查询,每次给出时间t,求至少打开多少个水管才能使得所有水库在t时间内被灌满。

    D分析:设打开x个水管,那么使得打开的水管最优必须是前面x个。考虑二分check(x,t) 开x个管道能否t秒灌满,显然只能支持O(1)的判断,灌满x后面的水库所需的时间好算,但需要保证前面的水库灌满。预处理一下,设dp[i]表示开前i个管道并灌满前i个水库所需的时间,可以O(n)解决。

    D代码:

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. #define int long long
    4. const int maxn=1e6+5;
    5. int a[maxn],sum[maxn];
    6. int dp[maxn],ot[maxn];//开前i个管道并灌满前i个水库所需的时间
    7. int n;
    8. int check(int x,int t)//开x个管道能否t秒灌满
    9. {
    10. int rem=max(sum[n]-sum[x]-ot[x],0ll);
    11. int tt=(rem+x-1)/x;
    12. if(tt+dp[x]<=t) return 1;
    13. return 0;
    14. }
    15. void solve()
    16. {
    17. cin>>n;
    18. for(int i=1;i<=n;i++)
    19. {
    20. cin>>a[i];
    21. sum[i]=sum[i-1]+a[i];
    22. }
    23. for(int i=1;i<=n;i++)
    24. {
    25. int t=max((a[i]-dp[i-1]-ot[i-1]+i-1)/i,0ll);
    26. dp[i]=dp[i-1]+t;
    27. ot[i]=dp[i]*i-sum[i];
    28. }
    29. int q;
    30. cin>>q;
    31. while(q--)
    32. {
    33. int t;
    34. cin>>t;
    35. int l=1,r=n,ans=-1;
    36. while(l<=r)
    37. {
    38. int m=l+r>>1;
    39. if(check(m,t))
    40. {
    41. r=m-1;
    42. ans=m;
    43. }
    44. else l=m+1;
    45. }
    46. cout<<ans<<endl;
    47. }
    48. }
    49. signed main()
    50. {
    51. ios::sync_with_stdio(0);
    52. int t=1;
    53. // cin>>t;
    54. while(t--) solve();
    55. }

  • 相关阅读:
    javascript复习之旅 9.1 从0到1认识`call apply`
    四种经典限流算法的实现思路以及各自的优缺点
    设计模式-责任链-笔记
    TCP/UDP协议
    Linux: 如何命令行安装R包
    python接口自动化-参数关联
    Solidity智能合约事件(event)
    电子协会 C语言 1级 29 、 对齐输出
    代码层面探索前端性能
    Springcloud的学习笔记(二)
  • 原文地址:https://blog.csdn.net/m0_55032066/article/details/125431575