[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 ...
随机推荐
- [poj 3281]最大流+建图很巧妙
题目链接:http://poj.org/problem?id=3281 看了kuangbin大佬的思路,还用着kuangbin板子orz http://www.cnblogs.com/kuangb ...
- [poj 3436]最大流+输出结果每条边流量
题目链接:http://poj.org/problem?id=3436 大力套kuangbin板过了orz #include<cstdio> #include<cstring> ...
- SpringMVC学习 -- @RequestParam , @RequestHeader , @CookieValue 的使用
使用 @RequestParam 绑定请求参数值: value:参数名 , 仅有一个 value 属性时 , value 可以省略不写. required:是否必须.默认为 true , 表示请求参数 ...
- 【bzoj3196-二逼平衡树】线段树套平衡树
http://acm.hust.edu.cn/vjudge/problem/42297 [题目描述] 写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间 ...
- bzoj2683/4066 简单题
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2683 http://www.lydsy.com/JudgeOnline/problem.ph ...
- COGS2090 Asm.Def找燃料
时间限制:1 s 内存限制:256 MB [题目描述] “听说咱们要完了?”比利·海灵顿拨弄着操纵杆,头也不回地问Asm.Def. “不要听得风就是雨.” “开个玩笑嘛.不就是打机器人,紧张啥,你 ...
- 【洛谷 UVA11417】 GCD(欧拉函数)
我们枚举所有gcd \(k\),求所有\(gcd=k\)的数对,记作\(f(k)\),那么\(ans=\sum_{i=1}^{n}(f(i)-1)*i\).为什么减1呢,观察题目,发现\(j=i+1\ ...
- 【mysql优化】大数据量分页优化
limit 翻页原理 limit offset,N, 当offset非常大时, 效率极低, 原因是mysql并不是跳过offset行,然后单取N行, 而是取offset+N行,返回放弃前offset行 ...
- 编写类du命令Python脚本
#!/usr/bin/env python #_*_ coding:utf-8 _*_ #计算整个目录的大小,脚本接受-H参数,来加上适当的单位 #功能像du看齐 import os,sys from ...
- C#区分大小写
连属性也是要区分大小写的,如 获取数据长度 错误:strs.length 这样是报错的 正确:strs.Length