https://lydsy.com/JudgeOnline/problem.php?id=1109
分析:
首先是dp,f[i]表示到第i个的最优值,f[i]=f[j]+1,(j<i,a[j]<a[i],j-a[j]<i-a[i]),三维偏序,可以cdq+线段树转移。实际上由a[j]<a[i]和j-a[j]<i-a[i]可以推出j<i所以二维偏序,直接LIS。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int N = 1000005; 20 21 struct Node{ 22 int x, c; 23 bool operator < (const Node &A) const { 24 return x == A.x ? c > A.c : x < A.x; 25 } 26 }A[N]; 27 int f[N]; 28 29 int main() { 30 int n = read(), cnt = 0; 31 for (int i = 1; i <= n; ++i) { 32 int x = read(); 33 if (i - x >= 0) 34 A[++cnt].x = x, A[cnt].c = i - x; 35 } 36 if (cnt == 0) { 37 cout << 0; return 0; 38 } 39 int len = 1; 40 sort(A + 1, A + cnt + 1); 41 f[1] = A[1].c; 42 for (int i = 2; i <= cnt; ++i) { 43 if (A[i].x != A[i - 1].x && A[i].c >= f[len]) f[++len] = A[i].c; 44 else { 45 int p = upper_bound(f + 1, f + len + 1, A[i].c) - f; 46 f[p] = A[i].c; 47 } 48 } 49 cout << len; 50 return 0; 51 } 52