zoukankan      html  css  js  c++  java
  • SPOJ 1557. Can you answer these queries II 线段树

    Can you answer these queries II

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    https://www.spoj.com/problems/GSS2/

    Description

    Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse to write two program of same kind at all. So he always failes in contests.

    When having a contest, Yang Zhe looks at the score of every problems first. For the problems of the same score, Yang Zhe will do only one of them. If he's lucky enough, he can get all the scores wanted.

    Amber is going to hold a contest in SPOJ. She has made a list of N candidate problems, which fit Yang Zhe very well. So Yang Zhe can solve any problem he want. Amber lined up the problems, began to select. She will select a subsequence of the list as the final problems. Being A girl of great compassion, she'd like to select such a subsequence (can be empty) that Yang Zhe will get the maximal score over all the possible subsequences.

    Amber found the subsequence easily after a few minutes. To make things harder, Amber decided that, Yang Zhe can take this contest only if Yang Zhe can answer her Q questions. The question is: if the final problems are limited to be a subsequence of list[X..Y] (1 <= X <= Y<= N), what's the maximal possible score Yang Zhe can get?

    As we know, Yang Zhe is a bit idiot (so why did he solve the problem with a negative score?), he got Wrong Answer again... Tell him the correct answer!

    Input

    • Line 1: integer N (1 <= N <= 100000);
    • Line 2: N integers denoting the score of each problem, each of them is a integer in range [-100000, 100000];
    • Line 3: integer Q (1 <= Q <= 100000);
    • Line 3+i (1 <= i <= Q): two integers X and Y denoting the ith question.

    Output

    • Line i: a single integer, the answer to the ith question.

    Sample Input

    9
    4 -2 -2 3 -1 -4 2 2 -6
    3
    1 2
    1 5
    4 9

    Sample Output

    4
    5
    3

    HINT

    题意

    给你n个数,查询区间最大连续子段和,并且区间内相同的数只计算一次

    题解:

    没有修改操作,很明显的离线线段树

    假设我们不考虑相同的数只计算一次的规则,我们应该怎么做呢?

    对于不断增加的r,我们维护c[i]表示从a[i]-a[r]的和,很显然,我们输出历史中最大的max(c[l],c[l+1],c[l+2]....c[r])就是答案了

    想一想感觉挺蠢的。。。

    我们怎么维护区间内相同的数只计算一次呢?对于每个数,我们只维护(pre[a[i]]+1,i)这个区间就好了嘛

    然后这道题就解决了

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long SgTreeDataType;
    struct treenode
    {
      int L , R  ;
      SgTreeDataType sum , lazy, cursum, prelazy;
      void updata(SgTreeDataType v)
      {
          sum += v;
          lazy += v;
          cursum = max(cursum,sum);
          prelazy = max(prelazy,lazy);
      }
    };
    
    treenode tree[500005];
    
    inline void push_down(int o)
    {
        SgTreeDataType Prelazy = tree[o].prelazy;
        SgTreeDataType Lazy = tree[o].lazy;
        tree[2*o].prelazy = max(tree[2*o].prelazy,tree[o*2].lazy + Prelazy);
        tree[2*o].cursum = max(tree[2*o].cursum,tree[o*2].sum + Prelazy);
        tree[2*o].lazy += Lazy; tree[2*o].sum += Lazy;
        tree[2*o+1].prelazy = max(tree[2*o+1].prelazy,tree[o*2+1].lazy + Prelazy);
        tree[2*o+1].cursum = max(tree[2*o+1].cursum,tree[o*2+1].sum + Prelazy);
        tree[2*o+1].lazy += Lazy; tree[2*o+1].sum += Lazy;
        tree[o].lazy = 0,tree[o].prelazy = 0;
    }
    
    inline void push_up(int o)
    {
        tree[o].sum = max(tree[2*o].sum,tree[2*o+1].sum);
        tree[o].cursum = max(tree[2*o].cursum,tree[2*o+1].cursum);
    }
    
    inline void build_tree(int L , int R , int o)
    {
        tree[o].L = L , tree[o].R = R,tree[o].sum = tree[o].lazy = tree[o].prelazy = tree[o].cursum = 0 ;
        if (R > L)
        {
            int mid = (L+R) >> 1;
            build_tree(L,mid,o*2);
            build_tree(mid+1,R,o*2+1);
        }
    }
    
    inline void updata(int QL,int QR,SgTreeDataType v,int o)
    {
        int L = tree[o].L , R = tree[o].R;
        if (QL <= L && R <= QR)
            tree[o].updata(v);
        else
        {
            push_down(o);
            int mid = (L+R)>>1;
            if (QL <= mid) updata(QL,QR,v,o*2);
            if (QR >  mid) updata(QL,QR,v,o*2+1);
            push_up(o);
        }
    }
    
    inline SgTreeDataType query(int QL,int QR,int o)
    {
        int L = tree[o].L , R = tree[o].R;
        if (QL <= L && R <= QR) return tree[o].cursum;
        else
        {
            push_down(o);
            int mid = (L+R)>>1;
            SgTreeDataType res = 0;
            if (QL <= mid) res =max(res, query(QL,QR,2*o));
            if (QR > mid) res =max(res,query(QL,QR,2*o+1));
            push_up(o);
            return res;
        }
    }
    
    int n,m;
    int a[100005];
    struct node
    {
        int l,r,id;
    };
    bool cmp(node A,node B)
    {
        return A.r<B.r;
    }
    node Query[100005];
    int pos[3000005];
    long long ans[1000005];
    int main()
    {
        memset(pos,0,sizeof(pos));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        build_tree(1,n,1);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&Query[i].l,&Query[i].r);
            Query[i].id = i;
        }
        sort(Query,Query+m,cmp);
        int N = 100005;
        for(int i=1,j=0;i<=n;i++)
        {
            updata(pos[a[i]+N]+1,i,a[i],1);
            pos[a[i]+N]=i;
            while(j<m&&Query[j].r==i)
            {
                ans[Query[j].id]=query(Query[j].l,Query[j].r,1);
                j++;
            }
        }
        for(int i=0;i<m;i++)
            printf("%lld
    ",ans[i]);
    }
  • 相关阅读:
    题解:SPOJ1026 Favorite Dice
    机器学习笔记
    机器学习第二次作业
    机器学习第一次作业
    2019软工实践总结作业
    软工2019作业6——软件评测
    2019软工作业五-实现师门树
    软件工程 “校园汇” 个人IDEA竞选分析与总结
    软工2019作业四
    软工2019作业三
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4993427.html
Copyright © 2011-2022 走看看