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;
}