首页 > 代码库 > codeforces332B - Maximum Absurdity 线段数 or dp

codeforces332B - Maximum Absurdity 线段数 or dp

题意:给你一个序列,找两个长度为 k 且没有重合区间的数使得其和最大

解题思路:

1)线段树

想了半天想不出只能先用线段树撸了一发,这题dp 第一名只要了 9分钟。

就是把起点为 i  长度为 k 的和预处理出来,再用线段树枚举去找。

解题代码:

  1 // File Name: 332b.cpp  2 // Author: darkdream  3 // Created Time: 2014年07月30日 星期三 08时10分45秒  4   5 #include<vector>  6 #include<list>  7 #include<map>  8 #include<set>  9 #include<deque> 10 #include<stack> 11 #include<bitset> 12 #include<algorithm> 13 #include<functional> 14 #include<numeric> 15 #include<utility> 16 #include<sstream> 17 #include<iostream> 18 #include<iomanip> 19 #include<cstdio> 20 #include<cmath> 21 #include<cstdlib> 22 #include<cstring> 23 #include<ctime> 24 #define LL long long  25 using namespace std; 26 #define M 200004 27 struct node{ 28   int l , r ,m;  29   LL maxn,s;  30 }tree[M <<2]; 31 LL a[200004]; 32 LL sum[200004]; 33 int L(int x) 34 { 35   return 2 * x;  36 } 37 int R(int x) 38 { 39    return 2 * x + 1;  40 } 41 void  pushup(int c) 42 { 43    if(tree[L(c)].maxn >=tree[R(c)].maxn) 44    { 45       tree[c].maxn = tree[L(c)].maxn; 46       tree[c].s = tree[L(c)].s; 47    }else{ 48       tree[c].maxn = tree[R(c)].maxn; 49       tree[c].s = tree[R(c)].s; 50    } 51 } 52 void build(int c ,int l, int r) 53 { 54       tree[c].l = l ; 55       tree[c].r = r ; 56       tree[c].m = (l+r)/2; 57       if(l == r) 58       { 59         tree[c].maxn = sum[l];  60         tree[c].s = l ;  61         return ;  62       } 63       build(L(c),l,tree[c].m); 64       build(R(c),tree[c].m+1,r); 65       pushup(c); 66 } 67 LL maxa;  68 int site; 69 void find(int c, int l , int r) 70 { 71     //printf("%d %d %d %d %d\n",c,tree[c].l,tree[c].r,l,r); 72      if(r <  l ) 73          return ;  74      if(l <= tree[c].l && r >= tree[c].r) 75      { 76          if(tree[c].maxn > maxa) 77          { 78            maxa = tree[c].maxn; 79            site = tree[c].s;  80          } 81          return ; 82      } 83      if(l <= tree[c].m) 84          find(L(c),l,r); 85      if(r > tree[c].m) 86          find(R(c),l,r); 87 } 88 int main(){ 89    int n , k; 90    scanf("%d %d",&n,&k); 91    int temp ; 92    a[0] = 0 ;  93    for(int i = 1; i <= n;i ++) 94    { 95        scanf("%d",&temp); 96        a[i] = a[i-1] + temp; 97    } 98    for(int i = 1 ;i <= n-k+1; i ++) 99    {100       sum[i] = a[i+k-1] - a[i-1];101    }102    build(1,1,n-k+1);103    LL  ans = -1e9;104    int a, b ; 105    for(int i =1 ;i <= n-k+1;i ++)106    {107       maxa = -1e9 ;108       site = 0 ; 109       find(1,i+k,n-k+1);110       if(sum[i] + maxa > ans)111       {112           ans  = sum[i] + maxa;113           a= i ; 114           b = site;115       }116    }117    printf("%d %d\n",a,b);118 return 0;119 }
View Code

 2)由第一种思路突然想到还可以预处理出来 i 以后 的最大值是多少,位置是多少,这样就可以直接dp了

 1 // File Name: 332b.1.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月30日 星期三 10时13分41秒 4  5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque>10 #include<stack>11 #include<bitset>12 #include<algorithm>13 #include<functional>14 #include<numeric>15 #include<utility>16 #include<sstream>17 #include<iostream>18 #include<iomanip>19 #include<cstdio>20 #include<cmath>21 #include<cstdlib>22 #include<cstring>23 #include<ctime>24 #define LL long long 25 #define maxn 200050 26 using namespace std;27 LL a[maxn];28 LL sum[maxn];29 LL m[maxn];30 int s[maxn];31 int n , k ; 32 int main(){33      scanf("%d %d",&n,&k);34      a[0] = 0 ; 35      int temp ; 36      for(int i = 1;i <=  n;i ++)37      {38         scanf("%d",&temp);39         a[i] =a[i-1]+ temp; 40      }41      int p = n - k + 1; 42      for(int i = 1;i <= p ; i ++)43      {44        sum[i] = a[i+k-1] - a[i-1];45      }46      m[p] = sum[p];47      s[p] = p ; 48     49      for(int i = p -1;i >= 1 ;i --)50      {51         if(sum[i] >= m[i+1])52         {53             m[i] = sum[i];54             s[i] = i ;55         }else{56            m[i] = m[i+1];57            s[i] = s[i+1];58         }59      }60      int a, b ;61      LL maxa = -1e9 ; 62      for(int i =1 ;i <= p;i ++)63      {64         if(sum[i] + m[i+k] > maxa) 65         {66            a = i ; 67            b = s[i+k];68            maxa = sum[i] + m[i+k];69         }70      }71      printf("%d %d\n",a,b);72 return 0;73 }
View Code