HDU - 4521 小明系列問題——小明序列 (dp + 線段樹)
題意
還是LIS,不過有一個限制條件是選擇的節點必須相差d。
思路
方程其實還是
(ps) 這題不離散竟然比離散還有快。。。是我寫搓了?
程式碼
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 1e5+10;
int tree[maxn<<2] , dp[maxn] , a[maxn],Hash[maxn] , cnt;
void pushup(int rt)
{
tree[rt] = max(tree[rt<<1] , tree[rt<<1|1]);
}
void update(int pos,int val,int l,int r,int rt)
{
if(l == r)
{
tree[rt] = max(tree[rt] , val);
return ;
}
int m = (l+r)>>1;
if(m>=pos) update(pos,val,lson);
else update(pos,val,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L>R) return 0;
if(L<=l && r<=R) return tree[rt];
int m = (l+r)>>1;
int ret = 0;
if(L<=m) ret = max(ret,query(L,R,lson));
if(R>m) ret = max(ret,query(L,R,rson));
return ret;
}
int main()
{
int n,d;
while(scanf("%d%d",&n,&d)!=EOF)
{
memset(tree,0,sizeof(tree));
cnt = 0;
for(int i = 1 ; i <= n ; i++)
{
scanf("%d",&a[i]);
Hash[cnt++] = a[i];
}
sort(Hash,Hash+cnt);
cnt = unique(Hash,Hash+cnt) - Hash;
for(int i = 1 ; i <= n ; i++) dp[i] = 1;
int ans = 0;
if(n < d + 2) {puts("1");continue;} // 沒有加這特判wa了一晚上
for(int i = d + 2 ; i <= n ;i ++)
{
int p = lower_bound(Hash,Hash+cnt,a[i]) - Hash + 1; // 當前點所在的大小
int p2 = lower_bound(Hash,Hash+cnt,a[i-d-1]) - Hash + 1; // 我們把第i-d-1這個數字放到線段樹裡,就可以完美的解決限制問題
update(p2,dp[i-d-1],1,n,1);
int te = query(1,p-1,1,n,1); // 查詢(1,p-1]裡的最大值,
// cout<<te<<endl;
dp[i] = te + 1;
ans = max(ans,dp[i]);
}
printf("%d\n",ans);
}
}