您的位置:首页 > 其它

Codeforces Round #271 (Div. 2) E Pillars(dp+线段树优化)

2014-10-07 18:56 351 查看
题目要求abs(d[i]-d[j])>=d,也就是说只要a[j]<=a[i]-d或者a[i]+d<=a[j] ,也就是只要求1~a[i]-d即a[i]+d~max里最大的dp值,这就是一个线段树查询问题。建议先看一下本博客里面LIS线段树优化的文章。

下面是AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int dp[100005],pre[100005];
LL s[100005],a[100005];
int b[100005];
struct pi{
int le;
int ri;
int ma;
}pp[400005];
void init(int tot,int l,int r){
pp[tot].ma=-1;
pp[tot].le=l;
pp[tot].ri=r;
if(l==r) return ;
init(2*tot,l,(l+r)/2);
init(2*tot+1,(l+r)/2+1,r);
}
void merg(int tot,int p,int n){
if(pp[tot].le==pp[tot].ri){
if(pp[tot].ma==-1) pp[tot].ma=n;
else{
if(dp[pp[tot].ma]<dp
){
pp[tot].ma=n;
}
}
return ;
}
int mid=(pp[tot].le+pp[tot].ri)/2;
if(p<=mid) merg(2*tot,p,n);
else merg(2*tot+1,p,n);
if(pp[2*tot].ma==-1) pp[tot].ma=pp[2*tot+1].ma;
if(pp[2*tot+1].ma==-1) pp[tot].ma=pp[2*tot].ma;
if(dp[pp[2*tot].ma]<dp[pp[2*tot+1].ma]) pp[tot].ma=pp[2*tot+1].ma;
else pp[tot].ma=pp[2*tot].ma;
}
int query(int tot,int l,int r){
int x,y;
if(l<=pp[tot].le&&r>=pp[tot].ri) return pp[tot].ma;
int mid;
mid=(pp[tot].le+pp[tot].ri)/2;
x=-1;
y=-1;
if(l<=mid) x=query(2*tot,l,r);
if(r>mid) y=query(2*tot+1,l,r);
if(x==-1) return y;
if(y==-1) return x;
if(dp[x]<dp[y]) return y;
return x;
}
int get(int n,LL k){
int le,ri,mid;
le=1;
ri=n;
while(le<=ri){
mid=(le+ri)/2;
if(s[mid]<k) le=mid+1;
else ri=mid-1;
}
return le;
}
int main()
{
int i,j,n,m,p,k,d,x,y;
LL a1,b1;
cin>>n>>d;
for(i=1;i<=n;i++){
cin>>a[i];
s[i]=a[i];
}
sort(s+1,s+1+n);
dp[0]=0;
init(1,1,n);
memset(pre,-1,sizeof(pre));
for(i=1;i<=n;i++){
if(i==1){
dp[1]=1;
p=get(n,a[i]);
merg(1,p,1);
}
else{
x=-1;
y=-1;
a1=a[i]-d;
if(a1>0){
p=get(n,a1);
if(p>n||s[p]!=a1) p--;
}
else p=0;
if(p>0)
x=query(1,1,p);
b1=a[i]+d;
p=get(n,b1);
if(p<=n) y=query(1,p,n);
if(x==-1&&y==-1) dp[i]=1;
else{
if(x==-1){
dp[i]=dp[y]+1;
pre[i]=y;
}
else if(y==-1){
dp[i]=dp[x]+1;
pre[i]=x;
}
else{
if(dp[x]<dp[y]){
dp[i]=dp[y]+1;
pre[i]=y;
}
else {
dp[i]=dp[x]+1;
pre[i]=x;
}
}
}
p=get(n,a[i]);
merg(1,p,i);
}
}
p=0;
for(i=1;i<=n;i++){
if(dp[i]>p) p=dp[i];
}
int tot;
printf("%d\n",p);
tot=0;
for(i=1;i<=n;i++){
if(dp[i]==p){
b[tot++]=i;
i=pre[i];
while(i!=-1){
b[tot++]=i;
i=pre[i];
}
break;
}
}
for(i=tot-1;i>=0;i--) printf(" %d",b[i]);
printf("\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: