BZOJ 1135: [POI2009]Lyz Hall定理 + 线段树

Description

初始时滑冰俱乐部有1到n号的溜冰鞋各k双。已知x号脚的人可以穿x到x+d的溜冰鞋。 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人。xi为负,则代表走了这么多人。 对于每次操作,输出溜冰鞋是否足够。
Input

n m k d ( 1≤n≤200,000 , 1≤m≤500,000 , 1≤k≤10^9 , 0≤d≤n ) ri xi ( 1≤i≤m, 1≤ri≤n-d , |xi|≤10^9 )
Output

对于每个操作,输出一行,TAK表示够 NIE表示不够。
Sample Input
4 4 2 1

1 3

2 3

3 3

2 -1

Sample Output
TAK

TAK

NIE

TAK

解题方法: 神题。 OTZ

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+5;
namespace segmenttree{
    LL lmax[maxn<<2], rmax[maxn<<2], smax[maxn<<2], sum[maxn<<2];
    void init(){
        memset(lmax, 0, sizeof(lmax));
        memset(rmax, 0, sizeof(rmax));
        memset(smax, 0, sizeof(smax));
        memset(sum, 0, sizeof(sum));
    }
    void pushup(int o){
        lmax[o] = max(lmax[o*2], sum[o*2] + lmax[o*2+1]);
        rmax[o] = max(rmax[o*2+1], sum[o*2+1] + rmax[o*2]);
        smax[o] = max(smax[o*2], smax[o*2+1]);
        smax[o] = max(smax[o], lmax[o*2+1] + rmax[o*2]);
        sum[o] = sum[o*2] + sum[o*2+1];
    }
    void update(int pos, LL v, int l, int r, int o){
        if(l == r){
            lmax[o] += v;
            rmax[o] += v;
            smax[o] += v;
            sum[o] += v;
            return ;
        }
        int mid = (l + r) / 2;
        if(pos <= mid) update(pos, v, l, mid, o*2);
        else update(pos, v, mid+1, r, o*2+1);
        pushup(o);
    }
}
int n, m, k, d;
int main(){
    using namespace segmenttree;
    init();
    scanf("%d%d%d%d", &n, &m, &k, &d);
    for(int i = 1; i <= n; i++) update(i, -k, 1, n, 1);
    while(m--){
        int x, r;
        scanf("%d%d", &r, &x);
        update(r, x, 1, n, 1);
        puts(smax[1] <= (LL)d*k ? "TAK" : "NIE");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值