国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

BZOJ 1109: [POI2007]堆積木Klo 神分析, LIS, BIT, 二分

2019-11-10 23:50:56
字體:
來源:轉載
供稿:網友

Description

  Mary在她的生日禮物中有一些積木。那些積木都是相同大小的立方體。每個積木上面都有一個數。Mary用他的 所有積木壘了一個高塔。媽媽告訴Mary游戲的目的是建一個塔,使得最多的積木在正確的位置。一個上面寫有數i 的積木的正確位置是這個塔從下往上數第i個位置。Mary決定從現有的高塔中移走一些,使得有最多的積木在正確 的位置。請你告訴Mary她應該移走哪些積木。 Input

  第一行為一個數n,表示高塔的初始高度。第二行包含n個數a1,a2,…,an,表示從下到上每個積木上面的數。 (1<=n<=100000,1<=ai<=1000000)。 Output

  注意:請輸出最多有多少點可以處在正確位置 Sample Input 5

1 1 2 5 4 Sample Output 3

解題方法: 我們先列一下普通的DP方程, dp[i]=max(dp[j]+1)(j<i,a[j]<a[i],a[i]?a[j]<=i?j)

然后這里就是3個限制條件了?CDQ三維偏序?翻了翻題解,發現神思路的題目。觀察三個限定條件。 1,j<i 2,a[j]<a[i] 3,a[i]?a[j]<=i?j

容易發現已知2,3可以推出1。 而1代表的是這n個數的排列順序。 而2的條件即為最長上升子序列。 所以我們不妨把3看做這n個數的重新排列法則,之后滿足2的條件即可。 所以我們只需要按照j?a[j]<=i?a[i]把n個數重新排列,接著求一個最長上升子序列長度即可。 需要注意的是,如果i?a[i]<0的話,那么顯然這個數不可能與C序列中的某個數對應上,直接跳過即可。

LIS可以二分也可以用樹狀數組的方法,PO爺用的樹狀數組的方法,可以看PO爺博客,蒟蒻寫了一個代碼和博主幾乎一樣的二分版本的代碼。

#include <bits/stdc++.h>using namespace std;const int maxn = 100010;const int maxm = 1000010;struct node{ int x, y; node(){} node(int x, int y) : x(x), y(y) {} bool Operator < (const node &rhs) const{ if(x == rhs.x) return y < rhs.y; return x < rhs.x; }}b[maxn];int n, cnt, ans, d[maxm], a[maxn];int main(){ scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); if(i - a[i] < 0) continue; b[++cnt].x = i - a[i], b[cnt].y = a[i]; } sort(b + 1, b + cnt + 1); memset(d, 0x3f, sizeof(d)); for(int i = 1; i <= cnt; i++) { int l = 1, r = ans, len = 0; while(l <= r){ int mid = (l + r) / 2; if(b[i].y > d[mid]){ len = mid, l = mid + 1; } else{ r = mid - 1; } } ans = max(ans, len + 1); d[len + 1] = min(d[len + 1], b[i].y); } cout << ans << endl; return 0;}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 成武县| 贺州市| 楚雄市| 张家港市| 醴陵市| 通榆县| 苏尼特左旗| 长岛县| 多伦县| 宜春市| 龙南县| 金阳县| 开阳县| 喜德县| 泰来县| 尤溪县| 忻州市| 亳州市| 澄城县| 高淳县| 林芝县| 湖北省| 白山市| 通山县| 泸西县| 怀仁县| 馆陶县| 全椒县| 昌邑市| 凤阳县| 垣曲县| 蒙城县| 无锡市| 东丽区| 丘北县| 忻州市| 泰宁县| 阿坝县| 泾源县| 泾源县| 清水县|