4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点


容易想到二分。
看到第一个条件容易想到缩点。
第二个条件自然是分段 然后让总和最小 容易想到dp.
缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的做法。
二分为重 发现变成了dp使得总a值尽可能小的问题。
方程为 f[i]=min(f[j]+max(j+1~i)a[k]); 这个问题容易使用线段树优化dp来解决。
单调栈维护决策区间修改即可。不过被卡常了 只有90points
const int MAXN=100010;
ll n,m,top,cnt,num;
ll b[MAXN],sum[MAXN],c[MAXN],fa[MAXN];
ll B[MAXN],L,R,s[MAXN],f[MAXN],w[MAXN],a[MAXN],A[MAXN];
struct jl{int l,r,id;ll sum;}g[MAXN<<2];
struct wy{int l,r;ll sum,tag;}t[MAXN<<2];
inline int getfather(int x){return x==fa[x]?x:fa[x]=getfather(fa[x]);}
inline void build(int p,int l,int r)
{
l(p)=l;r(p)=r;
if(l==r)return;
int mid=(l+r)>>1;
build(zz,l,mid);
build(yy,mid+1,r);
}
inline void pushdown(int p)
{
tag(zz)+=tag(p);
tag(yy)+=tag(p);
sum(zz)+=tag(p);
sum(yy)+=tag(p);
tag(p)=0;return;
}
inline void modify(int p,int x,ll w)
{
if(l(p)==r(p)){sum(p)=w;return;}
int mid=(l(p)+r(p))>>1;
if(tag(p))pushdown(p);
if(x<=mid)modify(zz,x,w);
else modify(yy,x,w);
sum(p)=min(sum(zz),sum(yy));
}
inline void cle(int p)
{
sum(p)=inf;tag(p)=0;
if(l(p)==r(p))return;
cle(zz);cle(yy);
}
inline void change(int p,int l,int r,ll x)
{
if(l<=l(p)&&r>=r(p))
{
sum(p)+=x;
tag(p)+=x;
return;
}
int mid=(l(p)+r(p))>>1;
if(tag(p))pushdown(p);
if(l<=mid)change(zz,l,r,x);
if(r>mid)change(yy,l,r,x);
sum(p)=min(sum(zz),sum(yy));
}
inline ll ask(int p,int l,int r)
{
if(l<=l(p)&&r>=r(p))return sum(p);
int mid=(l(p)+r(p))>>1;
ll cnt=inf;if(tag(p))pushdown(p);
if(l<=mid)cnt=min(cnt,ask(zz,l,r));
if(r>mid)cnt=min(cnt,ask(yy,l,r));
return cnt;
}
inline int check(ll x)//每一段的B的和都要<=mid
{
cle(1);
modify(1,0,0);
int flag=1,l=0;
rep(1,cnt,i)
{
while(flag<=num&&g[flag].id==i)
{
change(1,g[flag].l,g[flag].r,g[flag].sum);
++flag;
}
while(w[i]-w[l]>x)++l;
f[i]=ask(1,l,i-1);
modify(1,i,f[i]);
}
return f[cnt]<=m;
}
signed main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
get(n);get(m);sum[0]=INF;
rep(1,n,i)
{
get(a[i]);get(b[i]);fa[i]=i;
sum[i]=min(b[i],sum[i-1]);
}
rep(1,n,i)
{
if(sum[i-1]>a[i])continue;
int l=1,r=i-1;
while(l<r)
{
int mid=(l+r)>>1;
if(sum[mid]<=a[i])r=mid;
else l=mid+1;
}
//r为不合法左端点.
int w=i;
while(w>r)
{
int cc=getfather(w-1);
fa[w]=cc;w=cc;
}
}
rep(1,n,i)
{
int xx=getfather(i);
if(xx==i)
{
c[xx]=++cnt;
A[cnt]=a[i];
B[cnt]+=b[i];
}
else
{
A[c[xx]]=max(A[c[xx]],a[i]);
B[c[xx]]+=b[i];
}
L=max(L,B[c[xx]]);
}
rep(1,cnt,i)
{
w[i]=w[i-1]+B[i];
g[++num]=(jl){i-1,i-1,i,A[i]};
int last=i-1;
while(top&&A[i]>=A[s[top]])
{
g[++num]=(jl){s[top-1],last-1,i,A[i]-A[s[top]]};
last=s[top-1];--top;
}
s[++top]=i;
}
build(1,0,cnt);
R=w[cnt];
while(L<R)
{
ll mid=(L+R)>>1;
if(check(mid))R=mid;
else L=mid+1;
}
putl(L);return 0;
}
考虑另外一种优化dp的方法。
set 因为fi<=fi+1 所以对于被同一个a值笼罩的一段最左端节点是最优的 单调队列维护每一个这样的左端点即可。
当然 还有一个最优决策的来源可能是 最左端能用的节点 set维护前者即可。
const int MAXN=100010;
ll m;int n,top,cnt,num;
int b[MAXN],sum[MAXN],c[MAXN],fa[MAXN];
ll B[MAXN],L,R,s[MAXN],f[MAXN],w[MAXN],a[MAXN],A[MAXN],q[MAXN];
inline int getfather(int x){return x==fa[x]?x:fa[x]=getfather(fa[x]);}
multiset<ll>ss;
multiset<ll>::iterator it;
inline int check(ll x)//每一段的B的和都要<=mid
{
ss.clear();
int l=1,r,g=0;
rep(1,cnt,i)
{
while(l<=r&&(A[i]>=A[q[r]]))
{
if(l<r)it=ss.find(f[q[r-1]]+A[q[r]]),ss.erase(it);
--r;
}
q[++r]=i;
if(l<r)ss.insert(f[q[r-1]]+A[q[r]]);
while(w[i]-w[g]>x)++g;
while(q[l]<=g)
{
ss.erase(f[q[l]]+A[q[l+1]]);
++l;
}
f[i]=f[g]+A[q[l]];
if(l<r)f[i]=min(f[i],*ss.begin());
}
return f[cnt]<=m;
}
signed main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
get(n);scanf("%lld",&m);sum[0]=INF;
rep(1,n,i)
{
get(a[i]);get(b[i]);fa[i]=i;
sum[i]=min(b[i],sum[i-1]);
}
rep(1,n,i)
{
if(sum[i-1]>a[i])continue;
int l=1,r=i-1;
while(l<r)
{
int mid=(l+r)>>1;
if(sum[mid]<=a[i])r=mid;
else l=mid+1;
}
//r为不合法左端点.
int w=i;
while(w>r)
{
int cc=getfather(w-1);
fa[w]=cc;w=cc;
}
}
rep(1,n,i)
{
int xx=getfather(i);
if(xx==i)
{
c[xx]=++cnt;
A[cnt]=a[i];
B[cnt]+=b[i];
}
else
{
A[c[xx]]=max(A[c[xx]],a[i]);
B[c[xx]]+=b[i];
}
L=max(L,B[c[xx]]);
}
rep(1,cnt,i)w[i]=w[i-1]+B[i];
R=w[cnt];A[0]=inf;
while(L<R)
{
ll mid=(L+R)>>1;
if(check(mid))R=mid;
else L=mid+1;
}
putl(L);return 0;
}
4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点的更多相关文章
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- Contest Hunter 模拟赛09 A [线段树维护斜率]
题面 传送门 思路 首先看看我们到底要干什么:有$1e6$次询问,遍历$i$,每次要求一个形如$b_i \ast a_j - a_i \ast b_j$的东西的最大值 考虑如果一个$j$的决策在当前的 ...
- 4.3 省选模拟赛 序列游戏 dp
可以发现 某一段被删除后状态难以表示 也难以链接起来. 考虑暴力 有40分的状压dp 暴力存状态 然后枚举转移即可.最后注意和f[0]这个状态取max 不然一分都没有. const int MAXN= ...
- 4.12 省选模拟赛 LCA on tree 树链剖分 树状数组 分析答案变化量
LINK:duoxiao OJ LCA on Tree 题目: 一道树链剖分+树状数组的神题. (直接nQ的暴力有50. 其实对于树随机的时候不难想到一个算法 对于x的修改 暴力修改到根. 对于儿子的 ...
- 11.7 NOIP模拟赛
目录 2018.11.7 NOIP模拟 A 序列sequence(two pointers) B 锁lock(思路) C 正方形square(埃氏筛) 考试代码 B C 2018.11.7 NOIP模 ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- [10.18模拟赛] 序列 (DP)
[10.18模拟赛] 序列 题目描述 山山有一个整数序列s1,s2,-,sn,其中1≤si≤k. 求出有多少个准确移除m个元素后不同的序列.答案模(1e9+7) 输入 输入包括几个测试用例,并且由文件 ...
- 11/1 NOIP 模拟赛
11.1 NOIP 模拟赛 期望得分:50:实际得分:50: 思路:暴力枚举 + 快速幂 #include <algorithm> #include <cstring> #in ...
随机推荐
- Redis基础01-redis的数据结构
参考书:<redis设计与实现> Redis虽然底层是用C语言写的,但是底层的数据结构并不是直接使用C语言的数据结构,而是自己单独封装的数据结构: Redis的底层数据结构由,简单动态字符 ...
- P4408 逃学的小孩 题解
题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听说要考试,Chris的父母就心 ...
- 洛谷 P2882 [USACO07MAR]Face The Right Way G
题目传送门 题目描述 Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing ...
- DNP3协议解析 —— 利用Wireshark对报文逐字节进行解析详细解析Modbus所含功能码
现在网上有很多类似的文章.其实这一篇也借鉴了很多其他博主的文章. 写这篇文章的重点是在于解析功能和报文.对Dnp3这个协议并不会做很多介绍. 那我们就开始吧 上图则为dnp3协议整体的报文模型(点击红 ...
- mysql常用时间函数与类型转换
一.用到的函数有: 1.时间格式化函数 DATE_FORMAT(date,format) 2.时间加减函数DATE_ADD(date,INTERVAL expr unit)DATE_SUB(date ...
- 从零开始使用 Webpack 搭建 Vue3 开发环境
从零开始使用 Webpack 搭建 Vue3 开发环境 创建项目 首先需要创建一个空目录,在该目录打开命令行,执行 npm init 命令创建一个项目,这个过程会提示输入一些内容,完成后会自动生成一个 ...
- java 面向对象(二十五):内部类:类的第五个成员
内部类:类的第五个成员 1.定义: Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.2.内部类的分类:成员内部类(静态.非静态 ) vs 局部内部类(方法内.代码块内.构 ...
- Django适当进阶篇
本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣和效率最高的,今天就来基于下面的需求来继续学习Django 项 ...
- Quartz.Net系列(十四):详解Job中两大特性(DisallowConcurrentExecution、PersistJobDataAfterExecution)
1.DisallowConcurrentExceution 从字面意思来看也就是不允许并发执行 简单的演示一下 [DisallowConcurrentExecution] public class T ...
- Spring配置类深度剖析-总结篇(手绘流程图,可白嫖)
生命太短暂,不要去做一些根本没有人想要的东西.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习 ...