zoukankan      html  css  js  c++  java
  • cdoj844-程序设计竞赛 (线段树的区间最大连续和)【线段树】

    http://acm.uestc.edu.cn/#/problem/show/844

    程序设计竞赛

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    “你动规无力,图论不稳,数据结构松散,贪心迟钝,没一样像样的,就你还想和我同台竞技,做你的美梦!今天这场比赛,就是要让你知道你是多么的无能!!”

    不训练,无以为战。有n项能力是ACM竞赛要求的,训练则能提升,忽略则会荒废。

    m天,你能做到如何。

    Input

    第一行两个整数n,m,分别表示有n项能力要求,共有m天。

    第二行n个整数,第i个整数ai表示第i项能力的数值。

    接下来m行,每行开始先读入一个整数si,表明这是一次询问还是一次能力变化。

    si=0,表明这是一次询问,然后读入两个整数li,ri,表示询问在[li,ri]区间中任选一段连续序列,这段序列中所有能力值之和最大能是多少。

    si=1,表明这是一次能力变化,然后读入两个整数xi,wi,表示第xi项能力变为了wi。

    1≤n,m≤100000,−10000≤ai≤10000,1≤li≤ri≤n,1≤xi≤n,−10000≤wi≤10000

    Output

    有多少询问就输出多少行,每行输出一个整数,作为对该询问的回答。

    Sample input and output

    Sample InputSample Output
    4 4
    1 2 3 4
    0 1 3
    1 3 -3
    0 2 4
    0 3 3
    6
    4
    -3

    思路:

    每个节点维护4个值:
    summ:此区间内的最大连续和
    sum_:该节点以下的节点值得总和
    suml:此区间的从左端开始的最大连续和
    sumr:此区间的从右端开始的最大连续和
    合并区间时,该区间的最大连续和为:max(左子节点的最大连续和,右子节点的最大连续和,左子节点的最大右连续和+右子节点的最大左连续和)

    查询时返回一个整节点。因为每次要查询左子节点和右子节点,并且要比较它们的右连续最大和和左连续最大和,所以需要返回整个节点以便求值。

    代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 #define INF 0x7fffffff
     10 const int N=100005;
     11 int n,m,a[N];
     12 struct node
     13 {
     14     int left,right;
     15     int sum_,summ,suml,sumr;
     16 }tree[4*N];
     17 
     18 void build(int id,int l,int r);//建一棵线段树
     19 node query_sum(int id,int l,int r);//查询区间和
     20 void update(int id,int pos,int val);//更新位置pos的值
     21 
     22 int main()
     23 {
     24     //freopen("D:\input.in","r",stdin);
     25     //freopen("D:\output.out","w",stdout);
     26     int bo,t1,t2;
     27     scanf("%d%d",&n,&m);
     28     for(int i=1;i<=n;i++)
     29         scanf("%d",&a[i]);
     30     build(1,1,n);
     31     for(int i=1;i<=m;i++)
     32     {
     33         scanf("%d%d%d",&bo,&t1,&t2);
     34         if(bo)
     35             update(1,t1,t2);
     36         else{
     37             node tmp=query_sum(1,t1,t2);
     38             printf("%d
    ",tmp.summ);
     39         }
     40     }
     41     return 0;
     42 }
     43 void build(int id,int l,int r)
     44 {
     45     tree[id].left=l;
     46     tree[id].right=r;
     47     if(l==r)
     48     {
     49         tree[id].sum_=a[l];
     50         tree[id].summ=a[l];
     51         tree[id].suml=a[l];
     52         tree[id].sumr=a[l];
     53     }
     54     else
     55     {
     56         int mid=(l+r)/2;
     57         build(2*id,l,mid);
     58         build(2*id+1,mid+1,r);
     59         tree[id].sum_=tree[2*id].sum_+tree[2*id+1].sum_;
     60         tree[id].summ=max(max(tree[2*id].summ,tree[2*id+1].summ),(tree[2*id].sumr+tree[2*id+1].suml));
     61         tree[id].suml=max(tree[2*id].suml,tree[2*id].sum_+tree[2*id+1].suml);
     62         tree[id].sumr=max(tree[2*id+1].sumr,tree[2*id].sumr+tree[2*id+1].sum_);
     63     }
     64 }
     65 node query_sum(int id,int l,int r)
     66 {
     67     if(tree[id].left==l&&tree[id].right==r)
     68         return tree[id];
     69     else
     70     {
     71         node tmp,k1,k2;
     72         int flag1=0,flag2=0;
     73         int mid=(tree[id].left+tree[id].right)/2;
     74         if(r<=mid)  return query_sum(2*id,l,r);
     75         if(l>mid)   return query_sum(2*id+1,l,r);
     76         if(l<=mid){
     77             k1=query_sum(2*id,l,mid);
     78             flag1=1;
     79         }
     80         if(r>mid){
     81             k2=query_sum(2*id+1,mid+1,r);
     82             flag2=1;
     83         }
     84         if(flag1&flag2){
     85             tmp.sum_=k1.sum_+k2.sum_;
     86             tmp.suml=max(k1.suml,k1.sum_+k2.suml);
     87             tmp.sumr=max(k2.sumr,k1.sumr+k2.sum_);
     88             tmp.summ=max(max(k1.summ,k2.summ),k1.sumr+k2.suml);
     89         }else{
     90             if(flag1)   tmp=k1;
     91             else  tmp=k2;
     92         }
     93         return tmp;
     94     }
     95 }
     96 void update(int id,int pos,int val)
     97 {
     98     if(tree[id].left==tree[id].right)
     99     {
    100         tree[id].sum_=val;
    101         tree[id].summ=val;
    102         tree[id].suml=val;
    103         tree[id].sumr=val;
    104     }
    105     else
    106     {
    107         int mid=(tree[id].left+tree[id].right)/2;
    108         if(pos<=mid)    update(2*id,pos,val);
    109         else update(2*id+1,pos,val);
    110         tree[id].sum_=tree[2*id].sum_+tree[2*id+1].sum_;
    111         tree[id].summ=max(max(tree[2*id].summ,tree[2*id+1].summ),(tree[2*id].sumr+tree[2*id+1].suml));
    112         tree[id].suml=max(tree[2*id].suml,tree[2*id].sum_+tree[2*id+1].suml);
    113         tree[id].sumr=max(tree[2*id+1].sumr,tree[2*id].sumr+tree[2*id+1].sum_);
    114     }
    115 }
    View Code
  • 相关阅读:
    赋值、浅拷贝以及深拷贝的区别
    Python实现工厂模式
    Python实现代理模式
    select监听udp消息
    awk词频统计
    Python正则的贪婪和非贪婪示例
    js配置文件不缓存
    jquery事件命名空间和css-attr()
    iso移动Safari页面缓存
    javaWeb禁止http不安全请求方式
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4372653.html
Copyright © 2011-2022 走看看