【题解】 bzoj1135: [POI2009]Lyz (线段树+霍尔定理)

题面戳我

Solution

  • 二分图是显然的,用二分图匹配显然在这个范围会炸的很惨,我们考虑用霍尔定理。
  • 我们任意选取穿\(l,r\)的号码鞋子的人,那么这些人可以穿的鞋子的范围是\(l,r+d\),这个时候我们可以根据霍尔定理得出满足人人有鞋子穿的时候的式子是
    \(sum[i]\)表示穿\(i\)号鞋子的人数

\[\sum^r_{i=l} sum[i] \leq (r-l+1+d)*k \]

我们把这个式子整理下:

\[\sum^r_{i=l} (sum[i]-k) \leq d*k \]

  • 我们会发现右边是一个常量,那么这个式子就等价与左边的最大值小于等右边即满足,否则不满足
  • 所以我们就只需要找出\(1\rightarrow n\)中最大连续子序列。

New Knowledge

  • 最大连续子序列用线段树来维护,重难点在\(update\)
  • 向上更新
void update(int now,int nl,int nr){
  node[now].sum=node[ls(now)].sum+node[rs(now)].sum;
  node[now].lmax=max(node[ls(now)].lmax,node[ls(now)].sum+node[rs(now)].lmax);
  node[now].rmax=max(node[rs(now)].rmax,node[ls(now)].rmax+node[rs(now)].sum);
  node[now].maxx=max( node[ls(now)].rmax+node[rs(now)].lmax , 
                 max( node[ls(now)].maxx , node[rs(now)].maxx) );return;
}

Code

//It is coded by ning_mew on 7.18
#include<bits/stdc++.h>
#define ls(x) (x*2)
#define rs(x) (x*2+1)
#define LL long long
using namespace std;

const int maxn=2e5+7;

int n,m,d;LL k;
struct Node{LL lmax,rmax,maxx,sum;}node[maxn*4];

void update(int now,int nl,int nr){
  node[now].sum=node[ls(now)].sum+node[rs(now)].sum;
  node[now].lmax=max(node[ls(now)].lmax,node[ls(now)].sum+node[rs(now)].lmax);
  node[now].rmax=max(node[rs(now)].rmax,node[ls(now)].rmax+node[rs(now)].sum);
  node[now].maxx=max( node[ls(now)].rmax+node[rs(now)].lmax , max( node[ls(now)].maxx , node[rs(now)].maxx) );return;
}
void build(int now,int nl,int nr){
  if(nl==nr){node[now].sum=node[now].maxx=node[now].lmax=node[now].rmax=-k;return;}
  int mid=(nl+nr)/2;
  build(ls(now),nl,mid);build(rs(now),mid+1,nr);
  update(now,nl,nr);
}
void add(int now,int nl,int nr,int pl,LL ad){
  if(nl==nr&&nr==pl){
    LL box=node[now].sum+ad; node[now].sum=box;node[now].maxx=box;node[now].lmax=box;node[now].rmax=box; return;
  } if(nr<pl||pl<nl)return;
  int mid=(nl+nr)/2;
  add(ls(now),nl,mid,pl,ad);add(rs(now),mid+1,nr,pl,ad);
  update(now,nl,nr);
}
int main(){
  scanf("%d%d%lld%d",&n,&m,&k,&d);
  build(1,1,n);
  for(int i=1;i<=m;i++){
    int r;LL x;scanf("%d%lld",&r,&x);
    add(1,1,n,r,x);//cout<<node[1].maxx<<endl;
    if(node[1].maxx>d*k)printf("NIE\n");else printf("TAK\n");
  }return 0;
}

博主蒟蒻,随意转载。但必须附上原文链接:http://www.cnblogs.com/Ning-Mew/,否则你会场场比赛暴0!!!

posted @ 2018-08-23 17:27  Ning_Mew  阅读(290)  评论(0编辑  收藏  举报