如果某时不合法,那一定存在某段满足
(r−l+1+d)∗k<Σl≤i≤rnumi
(
r
−
l
+
1
+
d
)
∗
k
<
Σ
l
≤
i
≤
r
n
u
m
i
(其中 numi n u m i 表示 i i 号脚多少人)
移项,得
把所有 numi n u m i 减去k,只要判断最大连续和是否 >d∗k > 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;
}