• FZU2013 A short problem —— 线段树/树状数组 + 前缀和


    题目链接:https://vjudge.net/problem/FZU-2013

     Problem 2013 A short problem

    Accept: 356    Submit: 1083
    Time Limit: 1000 mSec    Memory Limit : 32768 KB

     Problem Description

    The description of this problem is very short. Now give you a string(length N), and ask you the max sum of the substring which the length can't small than M.

     Input

    The first line is one integer T(T≤20) indicates the number of the test cases. Then for every case, the first line is two integer N(1≤N≤1000000) and M(1≤M≤N).

    Then one line contains N integer indicate the number. All the number is between -10000 and 10000.

     Output

    Output one line with an integer.

     Sample Input

    2 5 1 1 -2 -2 -2 1 5 2 1 -2 -2 -2 1

     Sample Output

    1 -1

     Source

    FOJ有奖月赛-2011年03月

    题意:

    给出一个序列,求长度不小于m且和最大的子序列。

    题解:

    1.求出前缀和。

    2.将0插入到线段树第0位,然后从第m为开始枚举:去线段树范围为0~i-m的地方找最小值,然后以i为结尾的子序列最大值即为:sum[i] - query(1,0,n,0,i-m)。答案即为max(sum[i] - query(1,0,n,0,i-m))。

    3.类似的题目:CSU - 1551 Longest Increasing Subsequence Again

    线段树:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 1e6;
    18 
    19 int minv[MAXN*4];
    20 void add(int u, int l, int r, int x, int val)
    21 {
    22     if(l==r)
    23     {
    24         minv[u] = val;
    25         return;
    26     }
    27     int mid = (l+r)/2;
    28     if(x<=mid) add(u*2, l, mid, x, val);
    29     else add(u*2+1, mid+1,r, x, val);
    30     minv[u] = min(minv[u*2], minv[u*2+1]);
    31 }
    32 
    33 int query(int u, int l, int r, int x, int y)
    34 {
    35     if(l<=x&&y<=r)
    36         return minv[u];
    37 
    38     int mid = (l+r)/2;
    39     int ret = INF;
    40     if(x<=mid) ret = min(ret, query(u*2, l, mid, x, mid));
    41     if(y>=mid+1) ret = min(ret, query(u*2+1, mid+1, r, mid+1, y));
    42     return ret;
    43 }
    44 
    45 int sum[MAXN];
    46 int main()
    47 {
    48     int T, n, m;
    49     scanf("%d", &T);
    50     while(T--)
    51     {
    52         scanf("%d%d", &n,&m);
    53         sum[0] = 0;
    54         for(int i = 1; i<=n; i++)
    55         {
    56             int val;
    57             scanf("%d", &val);
    58             sum[i] = sum[i-1]+val;
    59         }
    60 
    61         for(int i = 0; i<=n*4; i++)
    62             minv[i] = INF;
    63 
    64         int ans = -INF;
    65         add(1,0,n,0,0);
    66         for(int i = m; i<=n; i++)
    67         {
    68             ans = max(ans, sum[i]-query(1,0,n,0,i-m));
    69             add(1,0,n,i-m+1,sum[i-m+1]);
    70         }
    71         printf("%d
    ", ans);
    72     }
    73 }
    View Code

    树状数组:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 1e6;
    18 
    19 int T, n, m;
    20 int lowbit(int x)
    21 {
    22     return x&(-x);
    23 }
    24 
    25 int c[MAXN];
    26 void add(int x, int d)
    27 {
    28     while(x<=n)
    29     {
    30         c[x] = min(c[x], d);
    31         x += lowbit(x);
    32     }
    33 }
    34 
    35 int query(int x)
    36 {
    37     int s = INF;
    38     while(x>0)
    39     {
    40         s = min(c[x], s);
    41         x -= lowbit(x);
    42     }
    43     return s;
    44 }
    45 
    46 int sum[MAXN];
    47 int main()
    48 {
    49     scanf("%d", &T);
    50     while(T--)
    51     {
    52         memset(c, 0, sizeof(c));
    53         scanf("%d%d", &n,&m);
    54         sum[0] = 0;
    55         for(int i = 1; i<=n; i++)
    56         {
    57             int val;
    58             scanf("%d", &val);
    59             sum[i] = sum[i-1]+val;
    60         }
    61         for(int i = 1; i<=n+1; i++)
    62             c[i] = INF;
    63 
    64         int ans = -INF;
    65         add(1, 0);
    66         for(int i = m; i<=n; i++)
    67         {
    68             ans = max(ans, sum[i]-query(i-m+1));
    69             add(i-m+2, sum[i-m+1]);
    70         }
    71         printf("%d
    ", ans);
    72     }
    73 }
    View Code
  • 相关阅读:
    差分约束
    POJ 2449 Remmarguts' Date[k短路]
    K短路
    hdu4034 Graph(floyd)
    hdu2089不要62(数位dp)
    POJ3468 A Simple Problem with Integers ( 线段树)
    POJ3255:Roadblocks(次短路 SPFA+A星)
    usaco2.1Ordered Fractions( 枚举, 数学)
    hdu1565方格取数(1) (状态压缩dp)
    poj3259 Wormholes(spfa)
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8537036.html
Copyright © 2020-2023  润新知