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

题面戳我

Solution

  • 二分图是显然的,用二分图匹配显然在这个范围会炸的很惨,我们考虑用霍尔定理。
  • 我们任意选取穿\(l,r\)的号码鞋子的人,那么这些人可以穿的鞋子的范围是\(l,r+d\),这个时候我们可以根据霍尔定理得出满足人人有鞋子穿的时候的式子是
    令\(sum[i]\)表示穿\(i\)号鞋子的人数
    \[\Sigma^r_{i=l} sum[i] \leq (r-l+1+d)*k\]
    我们把这个式子整理下:
    \[\Sigma^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!!!

原文地址:https://www.cnblogs.com/Ning-Mew/p/9331098.html

时间: 2024-11-05 19:39:00

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

BZOJ 1135 POI2009 Lyz 线段树+Hall定理

题目大意:有1~n型号的滑冰鞋,每种有k双,一个x号脚的人只能适应[x,x+d]号滑冰鞋,每次增加一些x号脚的人或减少一些x号脚的人,问能否匹配 http://m.blog.csdn.net/blog/u012732945/40707885 OTZ 这题我居然还能贡献一个WA真是醉了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M

【BZOJ1135】[POI2009]Lyz 线段树

[BZOJ1135][POI2009]Lyz 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

BZOJ 1135 [POI2009]Lyz 线段树

题意:链接 方法:线段树维护子区间最值. 解析: 我们可以推出来一个式子. 就是如果满足题意的话. 那么任意一个子区间[l,r] f[i]表示穿i的鞋的人数 (r?l+1+d)?k>=∑f[i](l<=i<=r) d?k>=∑(f[i]?k) 所以维护个区间最大值即可. 最大值比d*k小的话显然满足. 复杂度O(nlogn+mlogn); 代码: #include <cstdio> #include <cstring> #include <iostre

BZOJ1135: [POI2009]Lyz

1135: [POI2009]Lyz Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 264  Solved: 106[Submit][Status] Description 初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人.xi为负,则代表走了这么多人. 对于每次操作,输出溜冰鞋是否足够. Input n m k d ( 1≤n≤200,000 ,

BZOJ1798题解 Seq维护序列题解 双tag裸线段树

BZOJ1798题解 Seq维护序列题解 双tag裸线段树 1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 5549  Solved: 1951[Submit][Status][Discuss] Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)

题解:CF115E(线段树优化dp)

题目描述 你是一个赛车比赛的组织者,想在线性王国中安排一些比赛. 线性王国有n条连续的从左到右的道路.道路从左到右依次编号为从1到n,因此道路按照升序排列.在这些道路上可能会有几场比赛,每一场比赛都将使用这些道路的某个连续的子序列.而且,如果某场比赛举行了,你将获得一定数额的金钱.没有比赛在时间上重叠,所以每一段道路可以在多个比赛中使用. 不幸的是,所有道路的状况都不佳,需要修理.每条路都有与之相关的维修费用,你需要支付这笔费用来修理道路.只有在某场比赛中需要使用的所有道路都进行了修复,才能进行

一码学程 10284 排队找bug 题解 单调队列 或者 线段树RMQ

注:只是看到题目,未评测,所以不确定代码正确性,但是算法思路没有问题 描述 同学们的bug还真是多啊,orz... 春节期间大家存下的bug都来找肖老师解决了. 每个人都有bug,但是肖老师却只有一个啊.怎么办? 所以肖老师让大家按先来后到的顺序排队,一个一个的给大家解决. 这不一大早起来,肖老师就等着同学们过来解决bug了.不过肖老师偶尔想知道当前队伍中bug数量最少的是多少bug. sos xbug操作表示有一个同学有x个bug,并且过来排队等待肖老师解决. ok 操作表示肖老师已经解决了排

花神游历各国 题解(小清新线段树/树状数组+并查集)

众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于是我们关注一下开方本身的特殊性 我们知道,如果每次向下取整,一个数经过多次操作最终会变成1(或0) 事实上,大概经过 log(logx)次就会变成1 这是什么概念呢?经过博主测试,1e9只要经过五次开方取整就会变成1 那么接下来就能够利用1每次不必再操作优化复杂度 可以维护一个类似链表的结构,指向下一个>1的

[bzoj1135][Ceoi2011]Match_线段树

[Ceoi2011]Match 题目大意:初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人.xi为负,则代表走了这么多人. 对于每次操作,输出溜冰鞋是否足够. 数据范围: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 ) 题解: 这个题是个好题呀. 首先我们考虑,