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

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

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

2019-11-11 01:59:07
字體:
來源:轉載
供稿:網友

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;}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 三穗县| 奎屯市| 蒙阴县| 宁海县| 五台县| 张家港市| 军事| 东源县| 大新县| 新平| 邯郸市| 颍上县| 钟山县| 大足县| 惠州市| 滦南县| 雷波县| 东安县| 铁力市| 天全县| 长兴县| 甘谷县| 丹棱县| 凤翔县| 芮城县| 宜都市| 安塞县| 石阡县| 嘉禾县| 上杭县| 湖南省| 南城县| 桐城市| 六安市| 石渠县| 三都| 锡林浩特市| 邢台县| 浙江省| 阳谷县| 溆浦县|