zoukankan      html  css  js  c++  java
  • HDU3564 --- Another LIS (线段树维护最值问题)

    Another LIS

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1244    Accepted Submission(s): 431


    Problem Description
    There is a sequence firstly empty. We begin to add number from 1 to N to the sequence, and every time we just add a single number to the sequence at a specific position. Now, we want to know length of the LIS (Longest Increasing Subsequence) after every time's add.
     
    Input
    An integer T (T <= 10), indicating there are T test cases.
    For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
     
    Output
    For the k-th test case, first output "Case #k:" in a separate line, then followed N lines indicating the answer. Output a blank line after every test case.
     
    Sample Input
    1
    3
    0 0 2
     
    Sample Output
    Case #1:
    1
    1
    2
    Hint
    In the sample, we add three numbers to the sequence, and form three sequences. a. 1 b. 2 1 c. 2 1 3
     
    题意:一个空序列,第k次在xk处 插入 k,并输出 序列当前的LIS。
    首先 倒序 用线段树来确定每个元素 最终的位置。然后 求n次LIS,当然要用线段树维护了,,或者二分等等也可以。 nlogn
     1 #include <cstdio>
     2 #include <string>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 const int maxn = 1e5+10;
     8 int seg[maxn<<2],a[maxn];            // seg表示该区间 位置剩余量
     9 void build (int l,int r,int pos)
    10 {
    11     if (l == r)
    12     {
    13         seg[pos] = 1;
    14         return;
    15     }
    16     int mid = (l + r) >> 1;
    17     build(l,mid,pos<<1);
    18     build(mid+1,r,pos<<1|1);
    19     seg[pos] = seg[pos<<1] + seg[pos<<1|1];
    20 }
    21 int ans[maxn];                            //ans[i]表示 元素i的位置为ans[i]
    22 void Insert(int l,int r,int pos,int x,int k)
    23 {
    24     if (l == r)
    25     {
    26         ans[k] = l;
    27         seg[pos] = 0;
    28         return ;
    29     }
    30     int mid = (l + r) >> 1;
    31     if (seg[pos<<1] >= x)                            //左孩子的区间 位置剩余量大于x时,递归进入左孩子,否则右孩子同时 x-seg[pos<<1]
    32         Insert(l,mid,pos<<1,x,k);
    33     else
    34         Insert(mid+1,r,pos<<1|1,x - seg[pos<<1],k);
    35     seg[pos] = seg[pos<<1] + seg[pos<<1|1];
    36 }
    37 void update(int l,int r,int pos,int x,int v)
    38 {
    39     if (l == r)
    40     {
    41         seg[pos] = v;
    42         return;
    43     }
    44     int mid = (l + r) >> 1;
    45     if (x <= mid)
    46         update(l,mid,pos<<1,x,v);
    47     else
    48         update(mid+1,r,pos<<1|1,x,v);
    49     seg[pos] = max(seg[pos<<1],seg[pos<<1|1]);
    50 }
    51 int query(int l,int r,int pos,int ua,int ub)
    52 {
    53     if (ua <= l && ub >= r)
    54     {
    55         return seg[pos];
    56     }
    57     int mid = (l + r) >> 1;
    58     int t1 = 0,t2 = 0;
    59     if (ua <= mid)
    60         t1 = query(l,mid,pos<<1,ua,ub);
    61     if (ub > mid)
    62         t2 = query(mid+1,r,pos<<1|1,ua,ub);
    63     return max(t1,t2);
    64 }
    65 
    66 int main(void)
    67 {
    68     #ifndef ONLINE_JUDGE
    69         freopen("in.txt","r",stdin);
    70     #endif
    71     int t,cas = 1;
    72     scanf ("%d",&t);
    73     while (t--)
    74     {
    75         int n;
    76         scanf ("%d",&n);
    77         for (int i = 1; i <= n; i++)
    78             scanf ("%d",a+i);
    79         build (1,n,1);
    80         for (int i = n; i >= 1; i--)
    81             Insert(1,n,1,a[i] + 1,i);               //倒序 确定每个元素 最终的位置保存在ans里
    82         memset(seg,0,sizeof(seg));
    83         printf("Case #%d:
    ",cas++);
    84         for (int i = 1; i <= n; i++)
    85         {
    86             int t1 = query(1,n,1,1,n);
    87             int t2 = query(1,n,1,1,ans[i]);
    88             update(1,n,1,ans[i],t2+1);
    89             if (t2 < t1)                        //输出当前区间的LIS
    90                 printf("%d
    ",t1);
    91             else
    92                 printf("%d
    ",1+t2);
    93         }
    94         printf("
    ");
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    java~用域名回显照片
    java~-照片--用流回显源码
    java表单+多文件上传~~源代码
    java~生成二维码源代码
    html页面悬浮框--左边动画(隐藏凸出)---css设置
    html页面悬浮框--右边动画(隐藏凸出)---css设置
    java编写二维码
    java上传---表单+多文件上传
    js--a标签带参数href取值
    爬虫杂记
  • 原文地址:https://www.cnblogs.com/oneshot/p/4093807.html
Copyright © 2011-2022 走看看