• 【牛客】下雨天(思维)


    写在前面

      周末在家打牛客网,必出事

    题目描述

      小多有n个池塘,第i个池塘容量为i,一开始都没有水。
      随后的很多天,第i天的天气状况决定了所有水池同时的水量变化bi,bi>0表示在下雨,反之则表示在干旱。
      如果某个池塘满了,天还在下雨,那么多余的水就会白白流失掉。同样的,如果池塘干了还在干旱,池塘也不会出现负水量。更正式地说,设第k个水池当前水量为u,经历了某天,水量如果增加v,那么该水池在这天过后的水量为min(u+v,k);若v是个负数(水量减少),那么水量为max(0,u+v)。
      对于随后的q天,小多希望知道每一天结束时,所有池塘的总水量。

    输入描述

      第一行输入两个正整数n,q,表示小希的池塘数量和询问的天数。
      第二行起q行,第i行表示第i天的天气情况导致水量的变化。

    输出描述

      输出q行,每一行输出一个整数totali,表示在第i天结束时,所有池塘的总水量。
      示例1
      输入
      5 3
      1
      3
      -2
      输出
      5
      14
      5
      说明
      第一天池塘水量分别为1,1,1,1,1。
      第二天池塘水量分别为1,2,3,4,4。
      第三天池塘水量分别为0,0,1,2,2。
      备注:
      对于100%的数据,n≤109, q≤106, −109≤bi≤109

    分析

      牛客能看别人代码这点是真的爽

      感性理解一下,水量一定是长成这个样子的

     

      即水量一定是关于容量单增的,而且相邻容量之间最多差1,是一条斜率为1的斜线

      而且,每过一天最多产生一条斜线,还有可能消除之前的直线。

      所以,我们可以维护每一条斜线和整体的贡献。

      最多$q$条斜线,每条斜线消除,加入各是$O(1)$的,所以复杂度算下来大概就是$O(q)$的,感觉海星

      接下来考虑如何计算贡献

      显然,最终的答案就是框起来部分的面积。

     

      因为我们维护的是直线,为了方便计算,我们把它分割成这个亚子

      每条斜线可以对应一个梯形或者是三角形的面积

      所以只要维护每条斜线的右端点横坐标(绿线),左右端点高度差(红线)就可以计算每条斜线对应梯形的面积了

      (因为底部的长度是知道的,就是n(蓝线))

      于是我们可以用栈维护直线,每次水位变化时,找到哪些会被删除的直线,将它们暴力从栈弹出,顺便减去它们的贡献

      然后再看是否会形成新的直线,然后计算新的贡献加到答案里去

      Code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1000005;
    int n,q,en;long long x,ans,h[maxn],w[maxn];
    long long cal(long long h,long long w){return h*(h+1)/2+(n-w)*h;}
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%lld",&x);
            if(x>0)
            {
                while(en&&h[en]+x>=w[en])ans-=cal(h[en],w[en]),x+=h[en--];
                h[++en]=min(x,1ll*n);w[en]=min(x,1ll*n);
                ans+=cal(h[en],w[en]);
            }
            else
            {
                while(en&&h[en]+x<=0)ans-=cal(h[en],w[en]),x+=h[en--];
                if(en)ans-=cal(h[en],w[en]),h[en]+=x,ans+=cal(h[en],w[en]);
            }
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    如何自己手写一个热加载(转)
    阻塞I/O、非阻塞I/O和I/O多路复用、怎样理解阻塞非阻塞与同步异步的区别?
    Java NIO浅析 转至 美团技术团队
    mysql在线修改表结构大数据表的风险与解决办法归纳(转)
    MySQL性能优化
    Tomcat Connector(BIO, NIO, APR)三种运行模式(转)
    redis 单线程的理解
    Spring 中的bean 是线程安全的吗?
    Spring 自定义注解,结合AOP,配置简单日志注解 (转)
    redis 分布式锁
  • 原文地址:https://www.cnblogs.com/firecrazy/p/11831392.html
Copyright © 2020-2023  润新知