【BZOJ2013】[Ceoi2010]A huge tower
2013: [Ceoi2010]A huge tower
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 387 Solved: 260
[Submit][Status][Discuss]
Description
有N(2<=N<=620000)快砖,要搭一个N层的塔,要求:如果砖A在砖B上面,那么A不能比B的长度+D要长。问有几种方法,输出 答案 mod 1000000009的值
Input
第一行: N,D
第二行: N个数,表示每块砖的长度。
Output
方案数。输出要mod1000000009
Sample Input
4 1
1 2 3 100
1 2 3 100
Sample Output
4
HINT
Source
辣(si)鸡(lu)题目毁我人生
感谢lrh提供的思路
是这样的 我们考虑每一个元素能放在哪里
我们假设上一步的某一种方案是f
先排序,保证我一定能放在所有数的下方(不考虑该数原本的底下的数的大小)
我们会发现所有小于等于a[i]-d的都能放在a[i]下方,那么方案数ans[f]*=a[i]-d+1(放在0上头)
接下来我们要尝试证明为什么这样不会造成错误,即假如原本某个方案不合法,这样为什么能保证其依然不合法
我们举个例子 以样例例子
2 1 3 我们已经放好了三个数
这个时候,假如我们将100放到1 3或2 1中间,一定不能让方案成立(因为当前的数是前i个中最大的,将某个数替换后不会让答案变好只会让答案变差)
如果我们放在前边或者后边,方案也不可能成立,所以这部分答案不需要计算
代码实现非常短
/*To The End Of The Galaxy*/ #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<iomanip> #include<stack> #include<map> #include<set> #include<cmath> #define debug(x) cerr<<#x<<"="<<x<<endl #define INF 0x7f7f7f7f #define llINF 0x7fffffffffffll using namespace std; typedef pair<int,int> pii; typedef long long ll; inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } inline long long llinit() { long long now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } ll mod=1000000009LL; int n,a[1000001],d; int main() { ll ans=1; n=init();d=init(); for(int i=1;i<=n;i++) { a[i]=init(); } int id; sort(a+1,a+1+n); for(int i=1;i<=n;i++) { id=lower_bound(a+1,a+i,a[i]-d)-a; ans=ans*(i-id+1)%mod; } printf("%lld",ans); return 0; } /* srO xudyh davidlee1999WTK linkct1999 Orz compiler TDM-GCC 5.9.2 */