Try to find out the wrong in the test
Description
给出一个序列,第
i
个序列有两个关键值
接下来要求把序列分成若干段,保证对于每个位置
i
所属的段的长度
Data Constraint
n
<=
Solution
考虑最简单的
dp
。
设
fi
为
1
~
枚举一个
j
,判断
假设不存在
ci
的下限限制,仅考虑
di
的上限限制。
若仅考虑上限限制,那么能够转移到
fi
的
j
的取值范围必然是连续的一段且右端点为
显然这个
那么能够转移到
fi
的
j
即为
上限处理完了,接下来考虑比较麻烦的下限。
考虑分治。
设过程
考虑如何完成
solve(l,r)
,找到
l
+
记
ck
为
C
。
首先只有在
接下来对能被转移的
1、
lefti
≤
l
且
可以发现,随着
i
的递增,能够转移到的位置只不过多了一个
接着分析复杂度,首先线段树查询一次
log n
,总共
O(n log n)
。
剩下的复杂度与扫过的位置有关。
首先我们能够知道满足条件的
i
一定小于等于
当最小满足条件的
i
为
当最小满足条件的
i
为
由于最小满足条件的
i
应是
既有
T(n)=T(x)+T(n−x)+min(n−x,x)
,理解成启发式合并,所以总的时间复杂度为
O
(
2、
lefti
≤
l
且
此时每一个
复杂度显然为
O
(
3、
l
<
这样对于每个
可以发现对于每个
i
只会被至多进行一次线段树查询,故总复杂度为
4、
lefti
≥
k
不存在的,
当分治到区间[
l
,
详细实现请见代码。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll N=11e5,M=4*N,mo=1000000007;
ll f[N],g[N],zd[M],sol[M],l1[M],l2[M],w[N];
int c[N],d[N],lef[N],bits[N],r[N][21],dd[N];
int n,len,le,ri,z1,b[N];
ll z2;
inline int max(int a,int b)
{return a>b?a:b;}
inline int min(int a,int b)
{return a<b?a:b;}
inline int read()
{
int o=0; char ch=' ';
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';ch=getchar())o=o*10+ch-48;
return o;
}
int find(int le,int ri)
{
int op=bits[ri-le+1]-1,k=1<<op;
if(c[r[le][op]]>c[r[ri-k+1][op]])return r[le][op];else return r[ri-k+1][op];
}
inline void redo(int o)
{
if(zd[o<<1]>zd[(o<<1)^1])zd[o]=zd[o<<1],sol[o]=sol[o<<1];
else if(zd[o<<1]<zd[(o<<1)^1])zd[o]=zd[(o<<1)^1],sol[o]=sol[(o<<1)^1];
else zd[o]=zd[o<<1],sol[o]=(sol[o<<1]+sol[(o<<1)^1])%mo;
}
inline void down(int o)
{
// int ls=o<<1,rs=ls+1;
if(l1[o]>zd[o<<1])zd[o<<1]=l1[o<<1]=l1[o],sol[o<<1]=l2[o<<1]=l2[o];
else if(l1[o]==zd[o<<1])l1[o<<1]=l1[o],l2[o<<1]=(l2[o<<1]+l2[o])%mo,sol[o<<1]=(sol[o<<1]+l2[o])%mo;
if(l1[o]>zd[(o<<1)^1])zd[(o<<1)^1]=l1[(o<<1)^1]=l1[o],sol[(o<<1)^1]=l2[(o<<1)^1]=l2[o];
else if(l1[o]==zd[(o<<1)^1])l1[(o<<1)^1]=l1[o],l2[(o<<1)^1]=(l2[(o<<1)^1]+l2[o])%mo,sol[(o<<1)^1]=(sol[(o<<1)^1]+l2[o])%mo;
l1[o]=-n-1,l2[o]=0;
}
void build(int o,int l,int r)
{
zd[o]=-n-1;
if(l==r)return;
int mid=l+r>>1;
build(o<<1,l,mid); build((o<<1)^1,mid+1,r);
}
void check(int o,int l,int r,int le,int ri)
{
if(l==le&&r==ri){
if(zd[o]>z1)z1=zd[o],z2=sol[o];
else if(zd[o]==z1)z2=(z2+sol[o])%mo;
return;
}
if(l1[o]>0)down(o);
int mid=l+r>>1;
if(ri<=mid)check(o<<1,l,mid,le,ri);
else if(le>mid)check((o<<1)^1,mid+1,r,le,ri);
else {
check(o<<1,l,mid,le,mid);
check((o<<1)^1,mid+1,r,mid+1,ri);
}
redo(o);
}
void xg(int o,int l,int r)
{
if(r<le||l>ri)return;
if(l>=le&&r<=ri){
if(z1>zd[o])zd[o]=l1[o]=z1,sol[o]=l2[o]=z2;
else if(z1==zd[o])sol[o]=(sol[o]+z2)%mo,l1[o]=z1,l2[o]=(l2[o]+z2)%mo;
return;
}
if(l1[o]>0)down(o);
int mid=l+r>>1;
if(ri>=l&&le<=mid)xg(o<<1,l,mid);
if(ri>mid&&le<=r)xg((o<<1)^1,mid+1,r);
redo(o);
}
void move(int o,int l,int r,int posi)
{
if(l==r){
if(f[l]>zd[o])zd[o]=f[l],sol[o]=g[l];
else if(f[l]==zd[o])sol[o]=(sol[o]+g[l])%mo;
f[l]=zd[o]; g[l]=sol[o];
return;
}
if(l1[o]>0)down(o);
int mid=l+r>>1;
if(posi<=mid)move(o<<1,l,mid,posi);else move((o<<1)^1,mid+1,r,posi);
redo(o);
}
void solve(int l,int r)
{
if(l==r){
move(1,1,n,l);
return;
}
int k=find(l+1,r),cc=c[k];
solve(l,k-1);
int ty=max(k,l+cc);
if(ty>r){
solve(k,r);
return;
}
if(lef[ty]<=l){
z1=-n-1,z2=0; int bj=min(k+cc,r+1);
check(1,1,n,l,ty-cc);
++z1;
if(z1>f[ty])f[ty]=z1,g[ty]=z2;
else if(z1==f[ty])g[ty]=(g[ty]+z2)%mo;
for(++ty;lef[ty]<=l&&ty<bj;++ty){
int j=ty-cc;
if(f[j]+1>z1)z1=f[j]+1,z2=g[j];
else if(f[j]+1==z1)z2=(z2+g[j])%mo;
if(z1>f[ty])f[ty]=z1,g[ty]=z2;
else if(z1==f[ty])g[ty]=(g[ty]+z2)%mo;
}
if(ty>=bj&&ty<=r&&lef[ty]<=l){
int zb=ty,yb=r+1;
while(zb+1<yb){
int mid=zb+yb>>1;
if(lef[mid]<=l)zb=mid;else yb=mid;
}
le=ty; ri=zb;
xg(1,1,n);
ty=ri+1;
}
}
for(int i=ty;i<=r&&lef[i]<k;++i){
if(lef[i]>i-cc)continue;
z1=-n-1,z2=0;
check(1,1,n,lef[i],min(k-1,i-cc));
++z1;
if(z1>f[i])f[i]=z1,g[i]=z2;
else if(z1==f[i])g[i]=(g[i]+z2)%mo;
}
solve(k,r);
}
int main()
{
cin>>n;
build(1,1,n);
fo(i,1,n)c[i]=read(),d[i]=read();
fo(i,1,n)bits[i]=bits[i>>1]+1;
len=bits[n]-1;
fo(i,1,n)r[i][0]=i;
int u=1,v;
fo(l,1,len){
v=u,u<<=1;
fo(i,1,n-u+1)
if(c[r[i][l-1]]>c[r[i+v][l-1]])r[i][l]=r[i][l-1];else r[i][l]=r[i+v][l-1];
}
lef[0]=0; d[0]=n+1;
int le=1,ri=1; b[1]=0;
fo(i,1,n){
lef[i]=lef[i-1];
while(ri>=le&&d[i]<d[b[ri]])--ri;
b[++ri]=i;
while(lef[i]+d[b[le]]<i){
++lef[i];
if(lef[i]>=b[le])++le;
}
}
int zd=0;
fo(i,1,n)f[i]=-n-1;
fo(i,1,n)if(lef[i]==0){
zd=max(zd,c[i]);
if(i>=zd)f[i]=g[i]=1;
}else break;
solve(1,n);
if(f[n]<=0){
puts("-1");
return 0;
}
printf("%d ",f[n]);
printf("%lld",g[n]);
}