题目链接:点击这里
题目大意: 给定两个长度为
n
n
n 的序列
a
[
i
]
,
b
[
i
]
a[i],b[i]
a[i],b[i] 对于
a
[
i
]
a[i]
a[i] 序列,我们按顺序选择,对于每个
a
[
i
]
a[i]
a[i] 有选与不选两种选择,当且仅当
a
[
i
]
a[i]
a[i] 比前面的选择的元素大 时才可被选择,选择还有一个位置限制:只有在
[
i
?
b
i
,
i
)
[i-b_i,i)
[i?bi?,i) 下标内有元素被选择时
a
[
i
]
a[i]
a[i] 才可被选择 对于选择方案来说,如果有一个选择不同即认为是一种不同的方案,求总方案数
题目分析: 设
d
p
[
i
]
dp[i]
dp[i] 表示以选择了第
i
i
i 个元素结束的方案数 其转移方程为
d
p
[
i
]
=
∑
k
=
i
?
b
i
i
?
1
[
a
[
i
]
>
a
[
k
]
]
?
d
p
[
k
]
dp[i]=\sum_{k=i-b_i}^{i-1}[a[i]>a[k]]·dp[k]
dp[i]=∑k=i?bi?i?1?[a[i]>a[k]]?dp[k] (其中中括号
[
????
]
[\;\;]
[] 称为艾弗森括号,当括号内的表达式为真时,值为
1
1
1 否则为
0
0
0 ) 我们可以先对
a
[
i
]
a[i]
a[i] 进行排序,来保证当前所有的转移都满足
a
[
i
]
>
a
[
k
]
a[i]>a[k]
a[i]>a[k] ,然后把
d
p
dp
dp 数组用一个树状数组维护区间和就可以来达到
log
?
n
\log n
logn 转移 总体时间复杂度为
O
(
n
log
?
n
)
O(n\log n)
O(nlogn)
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<unordered_map>
#define ll long long
#define inf 0x3f3f3f3f
#define Inf 0x3f3f3f3f3f3f3f3f
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);
ch = getchar();
}
return res*flag;
}
namespace GenHelper
{
int z1,z2,z3,z4,z5,u,res;
int get()
{
z5=((z1<<6)^z1)>>13;
z1=((int)(z1&4294967)<<18)^z5;
z5=((z2<<2)^z2)>>27;
z2=((z2&4294968)<<2)^z5;
z5=((z3<<13)^z3)>>21;
z3=((z3&4294967)<<7)^z5;
z5=((z4<<3)^z4)>>12;
z4=((z4&4294967)<<13)^z5;
return (z1^z2^z3^z4);
}
int read(int m) {
u=get();
u>>=1;
if(m==0)res=u;
else res=(u/2345+1000054321)%m;
return res;
}
void srand(int x)
{
z1=x;
z2=(~x)^(0x23333333);
z3=x^(0x12345798);
z4=(~x)+51;
u = 0;
}
}
using namespace GenHelper;
const int maxn = 2e6+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int n,seed,a[maxn],b[maxn],c[maxn];
int lowbit(int u)
{
return u&(-u);
}
void add(int pos,int x)
{
while(pos <= n) c[pos] = (c[pos]+x)%mod,pos += lowbit(pos);
}
int query(int pos)
{
int res = 0;
if(pos <= 0) return 0;
while(pos) res = (res+c[pos])%mod,pos -= lowbit(pos);
return res;
}
pair<int,int>p[maxn];
int main()
{
n = read(),seed = read();
srand(seed);
for(int i = 1;i <= n;i++) a[i] = read(0),b[i] = read(i);
for(int i = 1;i <= n;i++) p[i].first = a[i],p[i].second = i;
sort(p+1,p+n+1);
for(int i = 1;i <= n;i++)
{
int id = p[i].second;
int cur = (query(id-1)-query(id-b[id]-1)+1+mod)%mod;
add(id,cur);
}
cout<<query(n)<<endl;
return 0;
}
|