[AGC009C]Division into 2
题意:
有一个长度为$N$的递增序列$S_i$,要把它分成$X,Y$两组,使得$X$中元素两两之差不小于$A$且$Y$中元素两两之差不小于$B$,求方案数
首先考虑$O\left(n^2\right)$的做法:
为了方便,我们令$S_0=-\infty$
设$f_{M,i,j}(M\in\{X,Y\},1\leq i\leq n,0\leq j\lt i)$表示已划分好$S_{1\cdots i}$且$S_j$是最后一个不属于$M$的元素的方案数
已算好$f_{X,1\cdots i,j}$和$f_{Y,1\cdots i,j}$,如何转移?
①若$S_{i+1}-S_i\geq A$,$S_{i+1}$可被放入$X$中,则$f_{X,i+1,0\cdots i-1}=f_{X,i,0\cdots i-1}$
否则$S_i,S_{i+1}$不可一起被放入$X$中,$f_{X,i+1,0\cdots i-1}=0$
②显然$f_{Y,i+1,i}=\sum\limits_{j=0}^{i-1}[S_{i+1}-S_j\geq B]f_{X,i,j}$
对$f_Y$的处理相似
最后的答案就是$\sum\limits_{i=0}^{n-1}f_{X,n,i}+\sum\limits_{i=0}^{n-1}f_{Y,n,i}$
#include<stdio.h>
#define ll long long
#define mod 1000000007
int fx[2010][2010],fy[2010][2010];
ll a[2010];
int main(){
int n,i,j;
ll A,B;
scanf("%d%lld%lld",&n,&A,&B);
for(i=1;i<=n;i++)scanf("%lld",a+i);
a[0]=-4223372036854775807ll;
fx[1][0]=fy[1][0]=1;
for(i=1;i<n;i++){
if(a[i+1]-a[i]>=A){
for(j=0;j<i;j++)fx[i+1][j]=fx[i][j];
}
if(a[i+1]-a[i]>=B){
for(j=0;j<i;j++)fy[i+1][j]=fy[i][j];
}
for(j=0;j<i;j++){
if(a[i+1]-a[j]>=B)fy[i+1][i]=(fy[i+1][i]+fx[i][j])%mod;
if(a[i+1]-a[j]>=A)fx[i+1][i]=(fx[i+1][i]+fy[i][j])%mod;
}
}
j=0;
for(i=0;i<n;i++)j=((j+fx[n][i])%mod+fy[n][i])%mod;
printf("%d",j);
}
考虑优化~
首先我们肯定不能开二维数组,考虑当前DP到$S_i$,只存$f_{M,j}$,并看一看当$i$变为$i+1$对答案的影响
因为$S$是递增的,所以满足$S_{i+1}-S_j\geq B$的$S_j$一定是一段前缀,所以我们可以用二分找到右端点并用线段树求区间和
其他转移就相当于线段树的单点更新
再用lazy tag实现清零即可
#include<stdio.h>
#define ll long long
#define mod 1000000007
int sumx[400010],sumy[400010],lazx[400010],lazy[400010],*laz,*sum,n;
ll a[100010];
void pushdown(int x){
if(laz[x]){
laz[x<<1]=laz[x<<1|1]=1;
sum[x<<1]=sum[x<<1|1]=0;
laz[x]=0;
}
}
int query(int L,int R,int l,int r,int x){
if(L<=l&&r<=R)return sum[x];
pushdown(x);
int mid=(l+r)>>1,ans=0;
if(L<=mid)ans=(ans+query(L,R,l,mid,x<<1))%mod;
if(mid<R)ans=(ans+query(L,R,mid+1,r,x<<1|1))%mod;
return ans;
}
void modify(int pos,int v,int l,int r,int x){
if(l==r){
sum[x]=(sum[x]+v)%mod;
return;
}
pushdown(x);
int mid=(l+r)>>1;
if(pos<=mid)
modify(pos,v,l,mid,x<<1);
else
modify(pos,v,mid+1,r,x<<1|1);
sum[x]=(sum[x<<1]+sum[x<<1|1])%mod;
}
int queryx(int L,int R){
laz=lazx;
sum=sumx;
return query(L,R,0,n-1,1);
}
void modifyx(int pos,int v){
laz=lazx;
sum=sumx;
modify(pos,v,0,n-1,1);
}
int queryy(int L,int R){
laz=lazy;
sum=sumy;
return query(L,R,0,n-1,1);
}
void modifyy(int pos,int v){
laz=lazy;
sum=sumy;
modify(pos,v,0,n-1,1);
}
int main(){
int i,l,r,mid,x,t1,t2;
ll A,B;
scanf("%d%lld%lld",&n,&A,&B);
for(i=1;i<=n;i++)scanf("%lld",a+i);
a[0]=-4223372036854775807ll;
modifyx(0,1);
modifyy(0,1);
for(i=1;i<n;i++){
l=0;
r=i-1;
while(l<=r){
mid=(l+r)>>1;
if(a[i+1]-a[mid]>=B){
x=mid;
l=mid+1;
}else
r=mid-1;
}
t1=queryx(0,x);
l=0;
r=i-1;
while(l<=r){
mid=(l+r)>>1;
if(a[i+1]-a[mid]>=A){
x=mid;
l=mid+1;
}else
r=mid-1;
}
t2=queryy(0,x);
if(a[i+1]-a[i]<A){
sumx[1]=0;
lazx[1]=1;
}
if(a[i+1]-a[i]<B){
sumy[1]=0;
lazy[1]=1;
}
modifyy(i,t1);
modifyx(i,t2);
}
printf("%d",(queryx(0,n-1)+queryy(0,n-1))%mod);
}
[AGC009C]Division into 2的更多相关文章
- AGC009C Division into Two
题意 有\(n\)个严格升序的数,请你分成两个集合\(A\)和\(B\),其中一个集合任意两数之差不小于\(x\),另一集合任意两数之差不小于\(y\). 问方案数,集合可以为空. $n \le 10 ...
- 【AGC009C】Division into Two
[AGC009C]Division into Two 题面 洛谷 题解 首先有一个比较显然的\(n^2\)算法: 设\(f_{i,j}\)表示\(A\)序列当前在第\(i\)个,\(B\)序列当前在第 ...
- python from __future__ import division
1.在python2 中导入未来的支持的语言特征中division(精确除法),即from __future__ import division ,当我们在程序中没有导入该特征时,"/&qu ...
- [LeetCode] Evaluate Division 求除法表达式的值
Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...
- 关于分工的思考 (Thoughts on Division of Labor)
Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...
- POJ 3140 Contestants Division 树形DP
Contestants Division Description In the new ACM-ICPC Regional Contest, a special monitoring and su ...
- 暴力枚举 UVA 725 Division
题目传送门 /* 暴力:对于每一个数都判断,是否数字全都使用过一遍 */ #include <cstdio> #include <iostream> #include < ...
- GDC2016【全境封锁(Tom Clancy's The Division)】对为何对应Eye Tracked System,以及各种优点的演讲报告
GDC2016[全境封锁(Tom Clancy's The Division)]对为何对应Eye Tracked System,以及各种优点的演讲报告 原文 4Gamer編集部:松本隆一 http:/ ...
- Leetcode: Evaluate Division
Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...
随机推荐
- Ubuntu下安装LNMP之独立添加php扩展模块
使用php的过程中,发现某个扩展没有添加,又不想重新编译php,这个时候我们就需要单独添加需要的扩展模块. 下面以mysqli扩展模块为例,具体介绍安装步骤. 1.安装mysql 具体参考:Ubunt ...
- ubuntu使用su切换root用户提示“认证失败”
在虚拟机上安装了ubuntu,安装时提示设置密码,也设置了,但是在终端操作时,遇到权限不够的问题,于是就想到就是要切换root用户,获取最高权限. 当我使用 su 切换到root用户时,提示我输入密码 ...
- [hdu 3949]线性基+高斯消元
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 一开始给做出来的线性基wa了很久,最后加了一步高斯消元就过了. 之所以可以这样做,证明如下. 首 ...
- HDU 多校对抗第三场 L Visual Cube
Problem L. Visual Cube Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java ...
- bzoj 4004 [JLOI2015]装备购买 拟阵+线性基
[JLOI2015]装备购买 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1820 Solved: 547[Submit][Status][Dis ...
- 迅雷Bolt图像拉伸不清晰的解决办法
迅雷Bolt库中的图像拉伸的效果锯齿比较严重,常见的导致锯齿的情况: 1.在使用ImageObject时,drawmode为1拉伸模式下: 2.使用Bitmap类的Stretch函数拉伸图像: 虽然I ...
- Java之戳中痛点 - (1)易变业务使用脚本语言编写
脚本语言的3大特征: 1.灵活:脚本语言一般是动态类型,可以不声明变量类型直接使用,也可以在运行期改变类型:2.便捷:脚本语言是解释性语言,在运行期变更非常方便,而不用重启服务3.简单:脚本语言语法比 ...
- hdu 2141 Can you find it?(二分查找)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2141 题目大意:查找是否又满足条件的x值. 这里简单介绍一个小算法,二分查找. /* x^2+6*x- ...
- [转]树莓派gpio口控制
0.前言 树莓派现在越来越火,网上树莓派的资料也越来越多.树莓派源自英国,国外嵌入式开源领域具有良好的分享精神,树莓派各种集成库也层出不穷,下面推荐几个. [[开发语言]——python [[ ...
- 使用MXNet远程编写卷积神经网络用于多标签分类
最近试试深度学习能做点什么事情.MXNet是一个与Tensorflow类似的开源深度学习框架,在GPU显存利用率上效率高,比起Tensorflow显著节约显存,并且天生支持分布式深度学习,单机多卡.多 ...