1109: [POI2007]堆积木Klo
1109: [POI2007]堆积木Klo
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
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 id, x, c; 23 bool operator < (const Node &A) const { 24 return c == A.c ? x < A.x : c < A.c; 25 } 26 }A[N], B[N]; 27 int f[N], mx; 28 29 #define Root 1, mx, 1 30 #define lson l, mid, rt << 1 31 #define rson mid + 1, r, rt << 1 | 1 32 struct SegmentTree{ 33 int mx[N << 2]; 34 SegmentTree() { for (int i = 0; i <= 4000000; ++i) mx[i] = -1e9; } 35 void update(int l,int r,int rt,int p,int v) { 36 if (l == r) { mx[rt] = v; return ; } 37 int mid = (l + r) >> 1; 38 if (p <= mid) update(lson, p, v); 39 else update(rson, p, v); 40 mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); 41 } 42 int query(int l,int r,int rt,int p) { 43 if (p < 1) return -1e9; 44 if (r <= p) return mx[rt]; 45 int mid = (l + r) >> 1; 46 if (p <= mid) return query(lson, p); 47 else return max(mx[rt << 1], query(rson, p)); 48 } 49 }T; 50 51 void cdq(int l,int r) { 52 if (l >= r) return ; 53 int mid = (l + r) >> 1; 54 cdq(l, mid); 55 for (int i = mid + 1; i <= r; ++i) B[i] = A[i]; 56 sort(B + mid + 1, B + r + 1); 57 for (int p = l, j = mid + 1; j <= r; ++j) { 58 if (f[B[j].id] == -1e9) continue; 59 while (p <= mid && A[p].c <= B[j].c) T.update(Root, A[p].x, f[A[p].id]), p ++; 60 f[B[j].id] = max(f[B[j].id], T.query(Root, B[j].x - 1) + 1); 61 } 62 for (int i = l; i <= mid; ++i) T.update(Root, A[i].x, 0); // B[i].x!!! 63 cdq(mid + 1, r); 64 sort(A + l, A + r + 1); 65 } 66 67 int main() { 68 int n = read(); 69 for (int i = 1; i <= n; ++i) { 70 A[i].x = read(), A[i].id = i, A[i].c = i - A[i].x; 71 if (A[i].x <= i) f[i] = 1; 72 else f[i] = -1e9; 73 mx = max(mx, A[i].x); 74 } 75 cdq(1, n); 76 int ans = 0; 77 for (int i = 1; i <= n; ++i) ans = max(ans, f[i]); 78 cout << ans; 79 return 0; 80 } 81