BZOJ[1135][POI2009]Lyz 线段树

21 篇文章 0 订阅

传送门ber~

如果某时不合法,那一定存在某段满足

(rl+1+d)k<Σlirnumi ( r − l + 1 + d ) ∗ k < Σ l ≤ i ≤ r n u m i

(其中 numi n u m i 表示 i i 号脚多少人)
移项,得
Σlirnumi(rl+1)k>dk

把所有 numi n u m i 减去k,只要判断最大连续和是否 >dk > d ∗ k 就可以,用线段树就可以了!

代码如下:

#include<algorithm>
#include<ctype.h>
#include<cstdio>
using namespace std;
inline int read(){
    int x=0,f=1;char c;
    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
    return x*f;
}
int n,m,k,d,x,y;
struct Node{
    int l,r;
    long long lsum,rsum,sum,maxx;
    Node *ls,*rs;
    Node(int _=0,int __=0):ls(NULL),rs(NULL),l(_),r(__){}
    inline void maintain(){
        if(l==r) return;
        sum=ls->sum+rs->sum;
        lsum=max(ls->lsum,ls->sum+rs->lsum);
        rsum=max(rs->rsum,rs->sum+ls->rsum);
        maxx=max(ls->maxx,max(rs->maxx,ls->rsum+rs->lsum));
    }
}*root;
void maketree(int l,int r,Node *&x){
    x=new Node(l,r);
    if(l==r){
        x->sum=x->maxx=x->lsum=x->rsum=-k;
        return;
    }
    int mid=l+r>>1;
    maketree(l,mid,x->ls);maketree(mid+1,r,x->rs);
    x->maintain();
}
void Add(int x,int v,Node *k){
    if(k->l==k->r){
        k->sum=k->rsum=k->lsum=k->maxx=k->sum+v;
        return;
    }
    int mid=k->l+k->r>>1;
    if(x<=mid) Add(x,v,k->ls);
    else Add(x,v,k->rs);
    k->maintain();
}
int main(){
    n=read();m=read();k=read();d=read();
    maketree(1,n,root);
    for(int i=1;i<=m;i++){
        x=read();y=read();
        Add(x,y,root);
        puts(root->maxx>1ll*d*k?"NIE":"TAK");
    }
return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值