[PA2014]Druzyny
题目描述
体育课上,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的更多相关文章
- P5979 [PA2014]Druzyny dp 分治 线段树 分类讨论 启发式合并
LINK:Druzyny 这题研究了一下午 终于搞懂了. \(n^2\)的dp很容易得到. 考虑优化.又有大于的限制又有小于的限制这个非常难处理. 不过可以得到在限制人数上界的情况下能转移到的最远端点 ...
- 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 ...
- @bzoj - 3711@ [PA2014]Druzyny
目录 @description@ @solution@ @accepted code@ @details@ @description@ 体育课上,n个小朋友排成一行(从1到n编号),老师想把他们分成若 ...
- Work at DP
转载请注明出处:http://www.cnblogs.com/TSHugh/p/8858805.html Prepared: (无notes的波兰题目的notes见我的波兰题目补全计划)BZOJ #3 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ 3721: PA2014 Final Bazarek
3721: PA2014 Final Bazarek Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 645 Solved: 261[Submit][ ...
- BZOJ 3709: [PA2014]Bohater
3709: [PA2014]Bohater Time Limit: 5 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1050 Solved: ...
- bzoj3714: [PA2014]Kuglarz
[PA2014]KuglarzTime Limit: 20 Sec Memory Limit: 128 MBSubmit: 553 Solved: 317[Submit][Status][Discus ...
- 【贪心】bzoj 3709:[PA2014]Bohater
3709: [PA2014]Bohater Time Limit: 5 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 653 Solved: ...
随机推荐
- Android 运行报错 Unknown failure (at android.os.Binder.execTransact(Binder.java:681)) Error while Installing APKs 解决办法
今天,我用手机测试的时候出现了这个错误 我网站查找了一会资料, 在运行的时候出现提示大致意思:卸载删除已存在应用程序,是否卸载现有应用程序,点击ok就会出现如下错误 原应用程序也没有卸载,然后自己手动 ...
- 学习安卓开发[3] - 使用RecyclerView显示列表
在上一篇学习安卓开发[2] - 在Activity中托管Fragment中了解了使用Fragment的好处和方法,本次记录的是在进行列表展示时RecyclerView的使用. RecyclerView ...
- Visual Studio无法调试
一.最近Visual studio调试不起来,运行完报错 二.解决方法 打开 调试>>>>选项>>>>常规>>>对ASP.NET启用 ...
- Headless Android开发板的调试及远程显示和控制
最近在调试msm8996的开发板,由于主板和LCD子板还没回来,所以先回的核心板算是个Headless的Android Device.核心板有独立供电,另外还有USB Type-C.FAN.HDMI. ...
- nginx配置静态项目
当nignx可以加载下面的这个service时 server { listen 8085; server_name 1.192.60.82; location / { root /etc/nginx ...
- 详解 OneAlert 排班可以帮你做什么
排班的存在,实质是通过有序安排,降低企业/团队人力成本,提升工作效率. 阅读导航(预计2min) 1. 详解排班功能 轮班机制 工作时间 双视图展示 灵活调整 2. 利用排班如何助力运维团队 排班 ...
- Spark读Hbase优化 --手动划分region提高并行数
一. Hbase的region 我们先简单介绍下Hbase的架构和Hbase的region: 从物理集群的角度看,Hbase集群中,由一个Hmaster管理多个HRegionServer,其中每个HR ...
- docker swarm的常用操作
1. 说明 本文档针对docker swarm操作. 针对的系统是以一个本地的测试系统为例.其中机器信息如下,172.16.1.13作为docker swarm的管理机. 本地测试的机器列表信息: 主 ...
- SQLServer之PRIMARY KEY约束
PRIMARY KEY约束添加规则 1.在表中常有一列或多列的组合,其值能唯一标识表中的每一行,这样的一列或多列成为表的主键(PrimaryKey). 2.一个表只能有一个主键,而且主键约束中的列不能 ...
- VS2017离线安装包[百度云盘](收藏了)
*************************************************************************************************** ...