• CSU


    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1551


    题意:

    给出一段序列, 删除其中一段连续的子序列(或者不删), 使得剩下的序列的最长上升连续子序列最大。



    题解:

    1.对于要删除的的子序列而言,要么夹在答案序列中间,要么在外面(删与不删对答案都没影响)。所以总体而言,答案序列被分成左右两半。

    2.用SL[i]记录从左边起以a[i]为结尾的最长上升连续子序列的长度, SR记录从右边起以a[i]为开始的最长上升连续子序列的长度。

    3.枚举SR[i],用线段树找出最大的SL[x](x的下标小于i),即SL[x]和SR[x]构成一段完整的序列, 期间一直更新线段树。



    学习之处:

    1.线段树/树状数组的动态使用,即边查询边更新。 

    类似的题: http://blog.csdn.net/DOLFAMINGO/article/details/65643894

    2.RMQ/线段树/树状数组的静态使用,即build()之后值进行查询操作。

    相关的题:http://blog.csdn.net/DOLFAMINGO/article/details/68953809       http://blog.csdn.net/dolfamingo/article/details/70306529



    线段树:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <string>
     6 #include <vector>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <sstream>
    11 #include <algorithm>
    12 using namespace std;
    13 #define pb push_back
    14 #define mp make_pair
    15 #define ms(a, b)  memset((a), (b), sizeof(a))
    16 #define eps 0.0000001
    17 typedef long long LL;
    18 const int INF = 2e9;
    19 const LL LNF = 9e18;
    20 const int mod = 1e9+7;
    21 const int maxn = 10000+10;
    22 
    23 int a[maxn], SL[maxn], SR[maxn], MAX[maxn<<2];
    24 int n;
    25 
    26 void update(int rt, int l, int r, int pos)
    27 {
    28     if(l==r)
    29     {
    30         MAX[rt] = max(MAX[rt], SL[pos]);
    31         return;
    32     }
    33 
    34     int mid = (l+r)>>1;
    35     if(a[pos]<=mid) update(rt*2, l, mid, pos);
    36     else update(rt*2+1 ,mid+1, r, pos);
    37 
    38     MAX[rt] = max(MAX[rt*2], MAX[rt*2+1]);
    39 }
    40 
    41 int query(int rt, int l, int r, int x, int y)
    42 {
    43     if(x<=l && y>= r)
    44         return MAX[rt];
    45 
    46     int mid = (l+r)>>1, ret = 0;
    47     if(x<=mid) ret = max(ret, query(rt*2, l, mid, x, y));
    48     if(y>=mid+1) ret = max(ret, query(rt*2+1, mid+1, r, x, y));
    49     return ret;
    50 }
    51 
    52 void solve()
    53 {
    54     for(int i = 1; i<=n; i++)
    55         scanf("%d",&a[i]);
    56 
    57     SL[1] = SR[n] = 1;
    58     for(int i = 2; i<=n; i++)
    59         SL[i] = (a[i]>a[i-1]?SL[i-1]+1:1);
    60     for(int i = n-1; i>0; i--)
    61         SR[i] = (a[i]<a[i+1]?SR[i+1]+1:1);
    62 
    63     int ans = 0;
    64     for(int i = 1; i<=n; i++)
    65     {
    66         int tmp = 0;
    67         if(a[i]>1) tmp = query(1, 1, 10000, 1, a[i]-1);
    68 
    69         ans = max(ans,SR[i]+tmp);
    70         update(1, 1, 10000, i);
    71 
    72     }
    73     printf("%d
    ",ans);
    74 }
    75 
    76 int main()
    77 {
    78     while(scanf("%d",&n)!=EOF)
    79     {
    80         ms(SL,0);
    81         ms(SR,0);
    82         ms(MAX,0);
    83         solve();
    84     }
    85 }
    View Code


    树状数组:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <string>
     6 #include <vector>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <sstream>
    11 #include <algorithm>
    12 using namespace std;
    13 #define pb push_back
    14 #define mp make_pair
    15 #define ms(a, b)  memset((a), (b), sizeof(a))
    16 #define eps 0.0000001
    17 typedef long long LL;
    18 const int INF = 2e9;
    19 const LL LNF = 9e18;
    20 const int mod = 1e9+7;
    21 const int maxn = 10000+10;
    22 
    23 int a[maxn], SL[maxn], SR[maxn], c[maxn];
    24 int n;
    25 
    26 int lowbit(int x)
    27 {
    28     return x&(-x);
    29 }
    30 
    31 void add(int x, int d)
    32 {
    33     while(x<maxn)
    34     {
    35         c[x] = max(c[x],d);
    36         x += lowbit(x);
    37     }
    38 }
    39 
    40 int sumc(int x)
    41 {
    42     int s = 0;
    43     while(x>0)
    44     {
    45         s = max(s,c[x]);
    46         x -= lowbit(x);
    47     }
    48     return s;
    49 }
    50 
    51 void solve()
    52 {
    53     for(int i = 1; i<=n; i++)
    54         scanf("%d",&a[i]);
    55 
    56     SL[1] = SR[n] = 1;
    57     for(int i = 2; i<=n; i++)
    58         SL[i] = (a[i]>a[i-1]?SL[i-1]+1:1);
    59     for(int i = n-1; i>0; i--)
    60         SR[i] = (a[i]<a[i+1]?SR[i+1]+1:1);
    61 
    62     int ans = 0;
    63     for(int i = 1; i<=n; i++)
    64     {
    65         int tmp = 0;
    66         if(a[i]>1) tmp = sumc(a[i]-1);
    67 
    68         ans = max(ans,SR[i]+tmp);
    69         add(a[i],SL[i]);
    70 
    71     }
    72     printf("%d
    ",ans);
    73 }
    74 
    75 int main()
    76 {
    77     while(scanf("%d",&n)!=EOF)
    78     {
    79         ms(SL,0);
    80         ms(SR,0);
    81         ms(c,0);
    82         solve();
    83     }
    84 }
    View Code


  • 相关阅读:
    主要几种通信协议的性能比较(转载)
    mina与spring集成(翻译)
    DF标志和串传送指令
    编写不会产生除法溢出的子程序
    转: 匈牙利标记法
    转:四种方式实现从尾到头输出单向链表(链表逆序打印)
    汇编语言注释标记符
    汇编将数据以十进制格式显示在屏幕上
    转:汇编寄存器的使用
    蒙特卡罗算法 求数组主元素
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7538713.html
Copyright © 2020-2023  润新知