牛客CSP-S提高组赛前集训营2 A 服务器需求

H y p e r l i n k Hyperlink Hyperlink

https://ac.nowcoder.com/acm/contest/1101/A


D e s c r i p t i o n Description Description

n n n天需要服务器,第 i i i天需要 a i a_i ai台,一台服务器能够服务 m m m天(这 m m m天可以不连续)

有一些天的需求会单天更改

求每次更改后最少需要多少台服务器

数据范围:
牛客CSP-S提高组赛前集训营2 A 服务器需求_第1张图片
a i ≤ 1 0 9 a_i\leq 10^9 ai109


S o l u t i o n Solution Solution

每次修改后的答案是 m a x { ∑ a i n , m a x { a i } } max\{\frac{\sum{a_i}}{n},max\{a_i\}\} max{nai,max{ai}}

证明显然

由于是单点修改,所以 s u m sum sum可以直接记录,用 s e t set set或其它数据结构维护即可,本人用的是线段树

如果改成区间修改,那么就不能用变量记录 s u m sum sum了,线段树仍然适用

所以线段树大法好(当然 S p l a y Splay Splay F H Q FHQ FHQ也nb)

时间复杂度: O ( ( n + q ) l o g n ) O((n+q)logn) O((n+q)logn)


C o d e Code Code

#include
#include
#include
#define lson k<<1
#define rson k<<1|1
#define LL long long
#define N 400010
using namespace std;
LL sum,mx,a[N],n,m,q,opt,x,y,t[N<<2];
inline LL read()
{
    char c;LL d=1,f=0;
    while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
inline void build(int k,int l,int r)
{
    if(l==r) {t[k]=a[l];return;}
    int mid=l+r>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    t[k]=max(t[lson],t[rson]);
    return;
}
inline void updata(int x,int d,int k=1,int l=1,int r=n)
{
    if(l==r) {a[x]+=d;t[k]=a[x];return;}
    int mid=l+r>>1;
    if(x<=mid) updata(x,d,lson,l,mid);
    else updata(x,d,rson,mid+1,r);
    t[k]=max(t[lson],t[rson]);
    return;
}
signed main()
{
//  freopen("1.txt","r",stdin);
//  freopen("2.txt","w",stdout);
    n=read();m=read();q=read();
    for(register int i=1;i<=n;i++) a[i]=read(),sum+=a[i];
    build(1,1,n);
    printf("%lld\n",max(sum/m+(sum%m?1:0),t[1]));
    while(q--)
    {
        x=read();y=read();
        sum+=y-a[x];
        updata(x,y-a[x]);
        printf("%lld\n",max(sum/m+(sum%m?1:0),t[1]));
    }
}

你可能感兴趣的:(线段树)