BZOJ1135: [POI2009]Lyz

【传送门:BZOJ1135


简要题意:

  给出1到n号的鞋子,每对鞋子有k对

  已知x号脚的人可以穿x到x+d号的鞋子

  给出m个操作,每个操作输入r,x,说明来了x个r号脚的人(如果x为负数,则说明走了x个)

  判断k对鞋子是否能够满足任何时刻所有人都有鞋穿


题解:

  二分图匹配显然会超时

  这时。。就应该膜题解

  Hall定理????wtf,膜一波


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
struct trnode
{
    int l,r,lc,rc;LL c,lm,rm,mx;
}tr[410000];int trlen;
void bt(int l,int r)
{
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;tr[now].c=tr[now].lm=tr[now].rm=tr[now].mx=0;
    tr[now].lc=tr[now].rc=-1;
    if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
void follow(int now)
{
    int lc=tr[now].lc,rc=tr[now].rc;
    tr[now].c=tr[lc].c+tr[rc].c;
    tr[now].lm=max(tr[lc].lm,tr[lc].c+tr[rc].lm);
    tr[now].rm=max(tr[rc].rm,tr[rc].c+tr[lc].rm);
    tr[now].mx=max(tr[lc].rm+tr[rc].lm,max(tr[lc].mx,tr[rc].mx));
}
void change(int now,int x,LL c)
{
    if(tr[now].l==tr[now].r)
    {
        tr[now].c=tr[now].mx=tr[now].lm=tr[now].rm+=c;
        return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(x<=mid) change(lc,x,c);
    else change(rc,x,c);
    follow(now);
}
int main()
{
    int n,m;LL k,d;
    scanf("%d%d%lld%lld",&n,&m,&k,&d);
    trlen=0;bt(1,n);
    for(int i=1;i<=n;i++) change(1,i,-k);
    for(int i=1;i<=m;i++)
    {
        int r;LL x;
        scanf("%d%lld",&r,&x);
        change(1,r,x);
        if(tr[1].mx<=d*k) printf("TAK\n");
        else printf("NIE\n");
    }
    return 0;
}

 

posted @ 2018-04-22 19:53  Star_Feel  阅读(188)  评论(0编辑  收藏  举报