• 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. }

  • 相关阅读:
    A02-HTML5入门
    django中的cookie与session
    Pyecharts绘制动态地图
    R语言和医学统计学(13):协方差分析
    SpringBoot集成Spring Security——【认证流程】
    tolua源码分析(十一)代码生成
    DC电源模块的优秀品质体现在哪些重要的关键参数
    [WinError 1455] 页面文件太小,无法完成操作和RuntimeError: CUDA out of memory
    15.2 主机探测与路由追踪
    Matlab的基本小知识
  • 原文地址:https://blog.csdn.net/m0_55032066/article/details/125431575