您的位置:首页 > 其它

BZOJ[1135][POI2009]Lyz 线段树

2018-02-06 15:08 253 查看
传送门ber~

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

(r−l+1+d)∗k<Σl≤i≤rnumi(r−l+1+d)∗k<Σl≤i≤rnumi

(其中numinumi表示ii号脚多少人)

移项,得

Σl≤i≤rnumi−(r−l+1)∗k>d∗kΣl≤i≤rnumi−(r−l+1)∗k>d∗k

把所有numinumi减去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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: