bzoj1135:[POI2009]Lyz

传送门

这个题首先考虑什么时候是NIE
显然是存在一段\([l,r]\)的人的总数>\(k*(r-l+1+d)\)
此时显然并不好维护,毕竟不等式两边都与长度有关,长度这个因素不能忽略
拆括号之后移下项:\(\sum_{i=l}^{r}v_i-k>k*d\)
现在可以忽略长度了,左边显然就是最大连续子段和,线段树搞就是了
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=5e5+10;
int n,m,k,d;
struct oo{int l,r;long long sum,lmx,rmx,mx;}s[maxn*4];
inline void update(int x)
{
    s[x].sum=s[x<<1].sum+s[x<<1|1].sum;
    s[x].mx=max(s[x<<1].rmx+s[x<<1|1].lmx,max(s[x<<1].mx,s[x<<1|1].mx));
    s[x].lmx=max(s[x<<1].lmx,s[x<<1].sum+s[x<<1|1].lmx);
    s[x].rmx=max(s[x<<1|1].rmx,s[x<<1|1].sum+s[x<<1].rmx);
}
inline void build(int x,int l,int r)
{
    s[x].l=l,s[x].r=r;int mid=(l+r)>>1;
    if(l==r){s[x].sum=s[x].lmx=s[x].rmx=s[x].mx=-k;return ;}
    build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    update(x);
}
inline void change(int x,int l,int v)
{
    if(s[x].l==s[x].r){s[x].sum=s[x].lmx=s[x].rmx=s[x].mx=s[x].sum+v;return ;}
    int mid=(s[x].l+s[x].r)>>1;
    if(l<=mid)change(x<<1,l,v);
    else change(x<<1|1,l,v);
    update(x);
}
int main()
{
    read(n),read(m),read(k),read(d);
    build(1,1,n);
    for(rg int i=1,x,y;i<=m;i++)
    {
        read(x),read(y),change(1,x,y);
        if(s[1].mx>1ll*k*d)printf("NIE\n");
        else printf("TAK\n");
    }
}

转载于:https://www.cnblogs.com/lcxer/p/10424234.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值