[BZOJ 1135][POI2009]Lyz
[BZOJ 1135][POI2009]Lyz
题意
初始时滑冰俱乐部有 \(1\) 到 \(n\) 号的溜冰鞋各 \(k\) 双。已知 \(x\) 号脚的人可以穿 \(x\) 到 \(x+d\) 的溜冰鞋。
有 \(m\) 次操作,每次包含两个数 \(r_i,x_i\) 代表来了 \(x_i\) 个 \(r_i\) 号脚的人。\(x_i\) 为负,则代表走了这么多人。 对于每次操作,输出溜冰鞋是否足够。足够输出 TAK, 否则输出 NIE.
\(n\le 2\times 10^5,m\le5\times 10^5,k\le1\times 10^9,d\in[0,n],1\le r_i\le n-d,|x_i|\le1\times 10^9\)
题解
被某Robbery少许加强后丢到了胡策里...
由霍尔定理, 二分图存在完美匹配当且仅当一侧的任意一个子集中的点连接的另一侧的点的数量都不小于这个子集的大小. 虽然看上去要枚举子集但是实际上我们发现不连续的几段更有可能满足霍尔定理的要求, 所以只要连续区间都满足霍尔定理的要求那么所有子集就都满足了. 感性证明如下:
假设选中了一个不连续的子集, 那么显然可以在不改变另外一侧的邻接情况下在当前子集中添加新的点. 如果不能添加新的点的话可以把子集拆成若干部分, 每个部分是一个连续段. 显然拆开后或者添加新点后更可能会破坏霍尔定理的要求.
也就是说如果设 \(i\) 号脚的人共有 \(s_i\) 个, 那么溜冰鞋不足当且仅当存在任意一个区间 \([l,r]\) 满足下式:
\]
那么我们拆开移项就可以得到:
\sum_{i=l}^rs_i-k(r-l+1)&>kd \\
\sum_{i=1}^r(s_i-k)&>kd
\end{aligned}
\]
于是就变成了一个支持单点加法的动态区间最大子段和问题. 线段树动态DP经典操作.
加强版里不保证 \(r\le n-d\), 需要继续考虑 \(r>n-d\) 的情况. 此时溜冰鞋不足的充要条件相当于:
\]
显然当 \(r=n\) 的时候左侧取到最大值, 我们只计算 \(r=n\) 时是否满足条件即可. 此时相当于:
\]
设 \(S\) 是 \(\langle s_i\rangle\) 的前缀和, 那么我们可以发现上式等价于:
S_n-S_{l-1}&>kn-k(l-1) \\
k(l-1)-S_{l-1}&>kn-S_n
\end{aligned}
\]
左侧的最大值显然也可以用线段树维护出来.
参考代码
#include <bits/stdc++.h>
const int MAXN=1e5+10;
typedef long long intEx;
struct Node{
struct Data{
intEx sum;
intEx lmax;
intEx maxs;
intEx rmax;
Data(){}
Data(intEx val){
this->sum=val;
this->lmax=this->rmax=this->maxs=std::max(this->sum,0ll);
}
Data friend operator+(const Data& a,const Data& b){
Data ans;
ans.sum=a.sum+b.sum;
ans.lmax=std::max(a.lmax,a.sum+b.lmax);
ans.rmax=std::max(a.rmax+b.sum,b.rmax);
ans.maxs=std::max(a.rmax+b.lmax,std::max(a.maxs,b.maxs));
return ans;
}
};
int l;
int r;
Data val;
Node* lch;
Node* rch;
Node(int,int);
void Maintain();
void Add(int,int);
};
int n;
int q;
int k;
int d;
int main(){
scanf("%d%d%d%d",&n,&q,&k,&d);
Node* N=new Node(1,n);
for(int i=0;i<q;i++){
int p,x;
scanf("%d%d",&p,&x);
N->Add(p,x);
if(N->val.maxs>1ll*k*d)
puts("NIE");
else
puts("TAK");
}
return 0;
}
Node::Node(int l,int r):l(l),r(r){
if(l==r)
this->val=Data(-k);
else{
int mid=(l+r)>>1;
this->lch=new Node(l,mid);
this->rch=new Node(mid+1,r);
this->Maintain();
}
}
void Node::Add(int x,int d){
if(this->l==this->r)
this->val=Data(this->val.sum+d);
else{
if(x<=this->lch->r)
this->lch->Add(x,d);
else
this->rch->Add(x,d);
this->Maintain();
}
}
inline void Node::Maintain(){
this->val=this->lch->val+this->rch->val;
}
加强版写的比较蠢...写了一个维护最大子段和的和一个区间加法区间最值的线段树...
#include <bits/stdc++.h>
const int MAXN=1e5+10;
typedef long long intEx;
struct Node{
struct Data{
intEx sum;
intEx lmax;
intEx maxs;
intEx rmax;
Data(){}
Data(intEx val){
this->sum=val;
this->lmax=this->rmax=this->maxs=std::max(this->sum,0ll);
}
Data friend operator+(const Data& a,const Data& b){
Data ans;
ans.sum=a.sum+b.sum;
ans.lmax=std::max(a.lmax,a.sum+b.lmax);
ans.rmax=std::max(a.rmax+b.sum,b.rmax);
ans.maxs=std::max(a.rmax+b.lmax,std::max(a.maxs,b.maxs));
return ans;
}
};
int l;
int r;
Data val;
Node* lch;
Node* rch;
Node(int,int);
void Maintain();
void Add(int,int);
};
struct NodeX{
int l;
int r;
intEx add;
intEx max;
NodeX* lch;
NodeX* rch;
NodeX(int,int);
void PushDown();
void Maintain();
void Add(int,int,int);
void Add(const intEx&);
};
int n;
int q;
int k;
int d;
int main(){
scanf("%d%d%d%d",&n,&q,&k,&d);
Node* N=new Node(1,n);
NodeX* K=new NodeX(0,n-1);
for(int i=0;i<q;i++){
int p,x;
scanf("%d%d",&p,&x);
N->Add(p,x);
if(p!=n)
K->Add(p,n-1,-x);
// printf("%lld %lld\n",N->val.maxs,K->max);
if(N->val.maxs>1ll*k*d||K->max>-N->val.sum)
puts("No");
else
puts("Yes");
}
return 0;
}
NodeX::NodeX(int l,int r):l(l),r(r),add(0){
if(l==r)
this->max=1ll*l*k;
else{
int mid=(l+r)>>1;
this->lch=new NodeX(l,mid);
this->rch=new NodeX(mid+1,r);
this->Maintain();
}
}
void NodeX::Add(const intEx& d){
this->add+=d;
this->max+=d;
}
void NodeX::Add(int l,int r,int d){
if(l<=this->l&&this->r<=r)
this->Add(d);
else{
this->PushDown();
if(l<=this->lch->r)
this->lch->Add(l,r,d);
if(this->rch->l<=r)
this->rch->Add(l,r,d);
this->Maintain();
}
}
void NodeX::PushDown(){
if(this->add){
this->lch->Add(this->add);
this->rch->Add(this->add);
this->add=0;
}
}
void NodeX::Maintain(){
this->max=std::max(this->lch->max,this->rch->max);
}
Node::Node(int l,int r):l(l),r(r){
if(l==r)
this->val=Data(-k);
else{
int mid=(l+r)>>1;
this->lch=new Node(l,mid);
this->rch=new Node(mid+1,r);
this->Maintain();
}
}
void Node::Add(int x,int d){
if(this->l==this->r)
this->val=Data(this->val.sum+d);
else{
if(x<=this->lch->r)
this->lch->Add(x,d);
else
this->rch->Add(x,d);
this->Maintain();
}
}
inline void Node::Maintain(){
this->val=this->lch->val+this->rch->val;
}

[BZOJ 1135][POI2009]Lyz的更多相关文章
- bzoj 1135 [POI2009]Lyz 线段树+hall定理
1135: [POI2009]Lyz Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 573 Solved: 280[Submit][Status][ ...
- 1135: [POI2009]Lyz
1135: [POI2009]Lyz https://lydsy.com/JudgeOnline/problem.php?id=1135 分析: hall定理+线段树连续区间的最大的和. 首先转化为二 ...
- 【BZOJ】1135: [POI2009]Lyz
题意 有\(1\)到\(n(1 \le n \le 200000)\)号的溜冰鞋各\(k(1 \le k \le 10^9)\)双.已知\(x\)号脚的人可以穿\(x\)到\(x+d\)的溜冰鞋. 有 ...
- BZOJ1135: [POI2009]Lyz
1135: [POI2009]Lyz Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 264 Solved: 106[Submit][Status] ...
- 【BZOJ1135】[POI2009]Lyz 线段树
[BZOJ1135][POI2009]Lyz Description 初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了x ...
- BZOJ 1115: [POI2009]石子游戏Kam
1115: [POI2009]石子游戏Kam Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 883 Solved: 545[Submit][Stat ...
- BZOJ 1142: [POI2009]Tab
1142: [POI2009]Tab Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 213 Solved: 80[Submit][Status][D ...
- bzoj 1133: [POI2009]Kon dp
1133: [POI2009]Kon Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 242 Solved: 81[Submit][Status][D ...
- bzoj 1138: [POI2009]Baj 最短回文路 dp优化
1138: [POI2009]Baj 最短回文路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 161 Solved: 48[Submit][Sta ...
随机推荐
- spring StopWatch用法
背景 有时我们在做开发的时候需要记录每个任务执行时间,或者记录一段代码执行时间,最简单的方法就是打印当前时间与执行完时间的差值,然后这样如果执行大量测试的话就很麻烦,并且不直观,如果想对执行的时间做进 ...
- 让 markdown 生成带目录的 html 文件
安装 npm install -g i5ting_toc 用法 进入 markdown 文件所在的文件夹 举个栗子: 你的sample.md文件放在桌面上 cd /Users/dora/Desktop ...
- Scrum 冲刺博客
博客链接集合 Alpha阶段敏捷冲刺 敏捷冲刺一 敏捷冲刺二 敏捷冲刺三 敏捷冲刺四 敏捷冲刺五 敏捷冲刺六 敏捷冲刺七 Alpha阶段敏捷冲刺总结 Alpha阶段敏捷冲刺总结
- ApiGen安装
# 首先,下载ApiGen(http://apigen.org/apigen.phar) # *nix系统 下载phar文件后, 移动到PATH目录中,以保证全局有权限调用 $ mv apigen.p ...
- Netbeans 8.0配置Python开发环境
1. 菜单栏:工具->插件->设置->添加 配置如下信息: http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/last ...
- python模块之xlwt
一. 安装 pip install xlwt 二. 使用 1. 创建excel(工作簿)对象 import xlwt wb = xlwt.Workbook() # 生成Workbook对象(xlwt. ...
- 使用WPF教你一步一步实现连连看(三)
这次首先对以前的结构进行了调整: 第一步:把MyButton按钮的属性独立成一个类,放在一个单独的MyButton.cs中,把图片的初始化也放到里面. 调整代码如下: public class MyB ...
- Scott用户的表结构
在Oracle的学习之中,重点使用的是SQL语句,而所有的SQL语句都要在scott用户下完成,这个用户下一共有四张表,可以使用: SELECT * FROM tab; 查看所有的数据表的名称,如果现 ...
- 【游记】CCHO TY国初划水记
没想到第一篇游记竟然是化学国初(其实是上次SXACM时候懒得写 DAY0 一下午做了5个小时的校车,服务区水真贵 肝了4个小时模拟题,颠到崩溃. 下榻在距离山大附不远的一个酒店,高三人好多哇,我们年级 ...
- eclipse .properties插件
资源文件 即 .properties 文件是常用于国际化: eclipse默认的 .properties 文件编辑器有几个问题: 编码问题 多种语言同步问题 下面介绍2种eclipse的 .prope ...