hdu 3564(线段树+LIS)
生活随笔
收集整理的這篇文章主要介紹了
hdu 3564(线段树+LIS)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:給出1~n的插入順序,要求每次插入之后的LIS
解題思路:這道題確實挺難想的,我最開始想用樹狀數組每插入一個數就更新一次,如果這么想,那么你就輸了。它這里的想法是先將1-n的最終位置都保存起來,然后再一個個去找LIS。這里有點離線算法的意思,至少了解到更新時可以先別急著處理。還有這里要總結一種線段樹的用法,就是在空格處去填充數字,確實結合了這道題的特點把線段樹用的很靈活。。。
參考的博客:http://blog.csdn.net/libin56842/article/details/13095801
#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 100005; struct Segment {int l,r;int cnt; //cnt記錄空位的數量 }tree[maxn<<2]; int n,len,pos[maxn],ans[maxn],dp[maxn];void build(int rt,int l,int r) {tree[rt].l = l, tree[rt].r = r;tree[rt].cnt = 1;if(l == r) return;int mid = (l + r) >> 1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);tree[rt].cnt = tree[rt<<1].cnt + tree[rt<<1|1].cnt; }void insert(int rt,int x,int m) //表示m要插入x的位置 {if(tree[rt].l == tree[rt].r){ans[m] = tree[rt].l;tree[rt].cnt = 0;return;}tree[rt].cnt--; //要插入一個數,表示這段區間內有一個空會被占if(x <= tree[rt<<1].cnt)insert(rt<<1,x,m);else insert(rt<<1|1,x-tree[rt<<1].cnt,m); }int binsearch(int val) {int l = 1, r = len, mid;while(l <= r){mid = (l + r) >> 1;if(val > dp[mid])l = mid + 1;else r = mid - 1;}return l; }int main() {int t,cas = 1;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i = 1; i <= n; i++){scanf("%d",&pos[i]);pos[i]++;dp[i] = 0;}build(1,1,n);for(int i = n; i >= 1; i--) //必須要逆著遍歷,因為最后一個加入的數是可以確定位置的,倒數第二個數在最后一個數確定的情況下再找位置,以此類推insert(1,pos[i],i); //也就是說,越往后加入進來的數,它選擇位置的權利更大,這是種逆向思維printf("Case #%d:\n",cas++);len = 0;for(int i = 1; i <= n; i++){int k = binsearch(ans[i]);len = max(len,k);dp[k] = ans[i];printf("%d\n",len);}printf("\n");}return 0; }
總結
以上是生活随笔為你收集整理的hdu 3564(线段树+LIS)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 3172(并查集+hash)
- 下一篇: 【开发工具】 JEECG_3.7新版开发