题目描述

体育课上,n个小朋友排成一行(从1到n编号),老师想把他们分成若干组,每一组都包含编号连续的一段小朋友,每个小朋友属于且仅属于一个组。
第i个小朋友希望它所在的组的人数不多于d[i],不少于c[i],否则他就会不满意。
在所有小朋友都满意的前提下,求可以分成的组的数目的最大值,以及有多少种分组方案能达到最大值。

题解

现在假设不考虑C的限制,那么它的转移是一段连续的区间我们可以用单调队列求出来这一段区间。

加上C的限制以后,我们不好直接处理,所以考虑分治。

假设我们当前处理的区间为[l,r]那么我们考虑取[l+1,r]Cmax作为中点,先分治左边,在计算跨越区间的贡献。

如果我们这样直接算的话复杂度不对,是T(n)=T(x)+T(n-x)+n=n^2

考虑到T(n)=T(x)+T(n-x)+min(x,n-x)=nlogn

所以我们考虑优化一下转移。

现在我们假设[l,mid-1]都算完了,一开始的转移指针在max(l+c[mid],mid)

然后我们再用一对左右指针维护当前合法的转移点,然后用线段树维护答案。

每次转移指针往后动的时候,右指针也会往右动一个,我们的答案是支持增量的,所以可以O(1)维护。

但是左指针往右动的时候,我们的答案是不支持减法的,所以还要继续在线段树上查。

当右端点不能懂得时候,我们把不同种类的左端点分别批量操作就好了。

从网上看到了一个复杂度证明:

代码

#include <bits/stdc++.h>
#define N 1000005
using namespace std;
const int mod=;
int c[N],lef[N],n;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct segmax{
int tr[N<<],id[N<<];
void build(int cnt,int l,int r){
if(l==r){tr[cnt]=c[l];id[cnt]=l;return;}
int mid=(l+r)>>;
build(cnt<<,l,mid);build(cnt<<|,mid+,r);
tr[cnt]=max(tr[cnt<<],tr[cnt<<|]);
id[cnt]=tr[cnt<<]>=tr[cnt<<|]?id[cnt<<]:id[cnt<<|];
}
void query(int cnt,int l,int r,int L,int R,int &ans1,int &ans2){
if(l>=L&&r<=R){
if(tr[cnt]>ans1){ans1=tr[cnt];ans2=id[cnt];}
return;
}
int mid=(l+r)>>;
if(mid>=L)query(cnt<<,l,mid,L,R,ans1,ans2);
if(mid<R)query(cnt<<|,mid+,r,L,R,ans1,ans2);
}
}T1;
struct node{
int mx,cnt;
node(int x=-1e9,int y=){mx=x;cnt=y;}
node operator +(const node &b)const{
if(mx==b.mx)return node(mx,(cnt+b.cnt)%mod);
else if(mx<b.mx)return b;else return *this;
}
node operator +(const int &b)const{return node(mx+b,cnt);}
}f[N];
struct segsum{
node tr[N<<],la[N<<];int ls[N<<],rs[N<<],ct;
segsum(){ct=;}
inline void pushdown(int cnt){
tr[ls[cnt]]=tr[ls[cnt]]+la[cnt];
tr[rs[cnt]]=tr[rs[cnt]]+la[cnt];
la[ls[cnt]]=la[ls[cnt]]+la[cnt];
la[rs[cnt]]=la[rs[cnt]]+la[cnt];
la[cnt]=node();
}
void build(int cnt,int l,int r){
if(l==r){if(l)tr[cnt]=node(-1e9,);else tr[cnt]=node(,);return;}
int mid=(l+r)>>;
rs[cnt]=++ct;ls[cnt]=++ct;
build(ls[cnt],l,mid);build(rs[cnt],mid+,r);
tr[cnt]=tr[ls[cnt]]+tr[rs[cnt]];
}
void upd(int cnt,int l,int r,int L,int R,node x){
if(l>=L&&r<=R){tr[cnt]=tr[cnt]+x;la[cnt]=la[cnt]+x;return;}
int mid=(l+r)>>;
if(la[cnt].cnt)pushdown(cnt);
if(mid>=L)upd(ls[cnt],l,mid,L,R,x);
if(mid<R)upd(rs[cnt],mid+,r,L,R,x);
tr[cnt]=tr[ls[cnt]]+tr[rs[cnt]];
}
void query(int cnt,int l,int r,int L,int R,node &x){
if(L>R)return;
if(l>=L&&r<=R){x=x+tr[cnt];return;}
int mid=(l+r)>>;
if(la[cnt].cnt)pushdown(cnt);
if(mid>=L)query(ls[cnt],l,mid,L,R,x);
if(mid<R)query(rs[cnt],mid+,r,L,R,x);
}
}T2;
inline int efs(int l,int r,int x){
int ans=;
while(l<=r){
int mid=(l+r)>>;
if(lef[mid]<=x)ans=mid,l=mid+;
else r=mid-;
}
return ans;
}
inline void work(int l,int mid,int r){
int i=max(c[mid]+l,mid);
int nowr=min(mid-,i-c[mid]),nowl=max(l,lef[mid]);node ans=node();
if(i>r||lef[i]>=mid)return;
T2.query(,,n,nowl,nowr,ans);if(ans.cnt)ans=ans+;
for(;i<=r;++i){
if(lef[i]>nowl){
if(lef[i]>=mid)return;
nowl=lef[i];
ans=node();
if(nowl<=nowr)T2.query(,,n,nowl,nowr,ans),ans=ans+;
}
f[i]=f[i]+ans;
nowr++;if(nowl<=nowr)ans=ans+(f[nowr]+);
if(nowr>mid-){nowr--;break;}
}
++i;
while(i<=r){
if(lef[i]>=nowl){
nowl=lef[i];
if(nowl>=mid)return;
}
ans=node();
T2.query(,,n,nowl,mid-,ans);if(ans.cnt)ans.mx++;
int t=efs(i,r,nowl);
T2.upd(,,n,i,t,ans);
i=t+;
}
}
void solve(int l,int r){
if(l>=r){node x=node();T2.upd(,,n,l,l,f[l]);T2.query(,,n,l,l,x);f[l]=x;return;}
int mx=,id=;
T1.query(,,n,l+,r,mx,id);
solve(l,id-);
work(l,id,r);
solve(id,r);
}
inline void prework(){
int q[N],d[N];
memset(q,,sizeof(q));memset(d,,sizeof(d));
n=rd();
for(int i=;i<=n;++i)c[i]=rd(),d[i]=rd();
int h=,t=,p=;
for(int i=;i<=n;++i){
while(h<=t&&d[q[t]]>=d[i])t--;
q[++t]=i;
while(h<=t&&i-p+>d[q[h]]){p++;while(h<=t&&q[h]<p)h++;}
lef[i]=p-;
}
}
int main(){
prework();
T1.build(,,n);
T2.build(,,n);
solve(,n);
node ans;
T2.query(,,n,n,n,ans);
if(!ans.cnt)puts("NIE");
else printf("%d %d",ans.mx,ans.cnt);
return ;
}

[PA2014]Druzyny的更多相关文章

  1. P5979 [PA2014]Druzyny dp 分治 线段树 分类讨论 启发式合并

    LINK:Druzyny 这题研究了一下午 终于搞懂了. \(n^2\)的dp很容易得到. 考虑优化.又有大于的限制又有小于的限制这个非常难处理. 不过可以得到在限制人数上界的情况下能转移到的最远端点 ...

  2. BZOJ3711 : [PA2014]Druzyny

    设f[i]为[1,i]分组的最优解,则 f[i]=max(f[j]+1),max(c[j+1],c[j+2],...,c[i-1],c[i])<=i-j<=min(d[j+1],d[j+2 ...

  3. @bzoj - 3711@ [PA2014]Druzyny

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 体育课上,n个小朋友排成一行(从1到n编号),老师想把他们分成若 ...

  4. Work at DP

    转载请注明出处:http://www.cnblogs.com/TSHugh/p/8858805.html Prepared: (无notes的波兰题目的notes见我的波兰题目补全计划)BZOJ #3 ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. BZOJ 3721: PA2014 Final Bazarek

    3721: PA2014 Final Bazarek Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 645  Solved: 261[Submit][ ...

  7. BZOJ 3709: [PA2014]Bohater

    3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1050  Solved: ...

  8. bzoj3714: [PA2014]Kuglarz

    [PA2014]KuglarzTime Limit: 20 Sec Memory Limit: 128 MBSubmit: 553 Solved: 317[Submit][Status][Discus ...

  9. 【贪心】bzoj 3709:[PA2014]Bohater

    3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 653  Solved:  ...

随机推荐

  1. Redis压缩列表

    此篇文章是主要介绍Redis在数据存储方面的其中一种方式,压缩列表.本文会介绍1. 压缩列表(ziplist)的使用场景 2.如何达到节约内存的效果?3.压缩列表的存储格式 4. 连锁更新的问题  5 ...

  2. windows下安装virtualenv并且配置指定环境

    下面是在windows下通过virtualenv创建虚拟环境, 包括 : 1. 安装virtualenv(使用pip可直接安装) 2. 使用virtualenv创建指定版本的虚拟环境 3. 进入虚拟环 ...

  3. mssql sqlserver 表增加列后,视图不会自动更新相关列的两种解决方法分享

    摘要: 今天对物理数据表,进行增加列操作后,程序一直显示无法找到相应列,通过仔细比对发现,视图中无相应列更新,下文将具体的解决方法分享如下: 例: create view vw_test as sel ...

  4. Clickhouse v18编译记录

    简介 ClickHouse是"战斗民族"俄罗斯搜索巨头Yandex公司开源的一个极具"战斗力"的实时数据分析数据库,是面向 OLAP 的分布式列式DBMS,圈内 ...

  5. Got a packet bigger than‘max_allowed_packet’bytes错误的解决方法

    通常项目上线前都有一些初始化数据需要导入,在今天博客系统发布前我使用sqlyog工具远程登录服务器的Mysql数据库,执行sql脚本对初始数据进行导入的时候报错: Got a packet bigge ...

  6. Hbase技术笔记

    一.Hbase介绍 二.Hbase的Region介绍 三.Hbase的写逻辑介绍 四.Hbase的故障恢复 五.Hbase的拆分和合并 如下ppt所示: 下面就来针对各个部分的内容来进行详细的介绍: ...

  7. 模拟vue的tag属性,在react里实现自定义Link

    我封装了一个简单的实现react里自定义Link的方法,方便大家使用. 因为普通组件没有metch.location.history等属性.只有在<Router>里面的<compon ...

  8. fastjson JSON 对象为空保留null

    JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(Object, SerializerFeature.WriteMapN ...

  9. 二 Struts2 接收数据

    struts2绑定页面参数三种方式1.普通属性:在action中写与页面参数相同的属性名,然后set方法2.用对象来接收:在action中写一个对象,表单元素名改为:对象名.属性名3.用实现Model ...

  10. KindEditor富文本编辑器使用

    我的博客本来打算使用layui的富文本编辑器,但是出了一个问题,无法获取编辑器内容,我参考官方文档,获取内容也就那几个方法而已,但是引入进去后始终获取的值为空,百度和bing都试过了,但是始终还是获取 ...