• UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)


    题意:求一个动态区间的最大连续和。

    静态版本的O(n)算法显示不适用了,但是可以用线段树分治,因为一个连续和要在两边的区间,要么跨越两边,对于一个结点维护最大前缀和,后缀和,子区间连续和。

    题目要求输出区间,所以还要保存连续和最大的区间,以及前缀和,后缀和的位置。为了维护最大前缀和以及后缀和还需要一个区间和。

    写的时候稍微麻烦一点,更新写成一个函数会方便很多。还好一遍过了。。。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 5e5+2;
    typedef long long ll;
    struct Seg
    {
        ll pre,suf,sub,sum;
        int l,r,pr,sl;
    }tr[maxn<<2];
    #define lid (id<<1)
    #define rid (id<<1|1)
    int n,m,a[maxn];
    int ql,qr;
    
    void updata(Seg&u,Seg&v1,Seg&v2)
    {
        if(v1.pre >= v1.sum+v2.pre){//y
            u.pr = v1.pr; u.pre = v1.pre;
        }else {
            u.pr = v2.pr; u.pre = v1.sum+v2.pre;
        }
    
        if(v2.suf <= v2.sum+v1.suf){//x
            u.sl = v1.sl; u.suf = v2.sum+v1.suf;
        }else {
            u.sl = v2.sl; u.suf = v2.suf;
        }
    
        if(v1.sub >= v2.sub){
            u.l = v1.l; u.r = v1.r; u.sub = v1.sub;
        }else {
            u.l = v2.l; u.r = v2.r; u.sub = v2.sub;
        }
        if(u.sub < v1.suf+v2.pre || (u.sub == v1.suf+v2.pre && (u.l>v1.sl ||(u.l == v1.sl && u.r > v2.pr) ) ) ){
            u.sub = v1.suf+v2.pre; u.l = v1.sl; u.r = v2.pr;
        }
    
        u.sum = v1.sum + v2.sum;
    }
    
    void build(int l = 1,int r = n,int id = 1)
    {
      if(l == r) {
         Seg &u = tr[id]; u.pre
    = u.suf = u.sub = u.sum = a[l]; u.l = u.r = u.pr = u.sl = l; return; } int mid = (l+r)>>1, lc = lid, rc = rid; build(l,mid,lc); build(mid+1,r,rc); updata(tr[id],tr[lc],tr[rc]); } Seg query(int l = 1,int r = n, int id = 1) { if(ql<=l&&r<=qr) { return tr[id]; } int mid = (l+r)>>1, lc = lid, rc = rid; Seg ret; if(ql<=mid && mid<qr){ Seg L = query(l,mid,lc), R = query(mid+1,r,rc); updata(ret,L,R); return ret; } if(qr <= mid) { return query(l,mid,lc); } return query(mid+1,r,rc); } int main() { //freopen("in.txt","r",stdin); int kas = 0; while(~scanf("%d%d",&n,&m)){ for(int i = 1; i <= n; i++) scanf("%d",a+i); build(); printf("Case %d: ",++kas); while(m--){ int x,y; scanf("%d%d",&x,&y); ql = x,qr = y; Seg ans = query(); printf("%d %d ",ans.l,ans.r); } } return 0; }
  • 相关阅读:
    sikiA计划问题记录
    列表+泛型
    查看别人项目找代码的方法
    Unity3d 异常与解决方案集合(持续)
    实现继承+接口继承+虚方法+隐藏方法+this/base+抽象类+密封类/方法+修饰符
    定义类+类实例化+属性+构造函数+匿名类型var+堆与栈+GC回收机制+值类型与引用类型
    局部变量和成员变量的区别
    数组元素二分查找(折半查找)
    数组元素冒泡排序
    数组元素选择排序
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4792519.html
Copyright © 2020-2023  润新知