首页 > 其他分享 >SP1557 GSS2 - Can you answer these queries II

SP1557 GSS2 - Can you answer these queries II

时间:2022-08-31 10:00:06浏览次数:89  
标签:pre these sum 离线 SP1557 II 区间 维护 我们

SP1557 GSS2 - Can you answer these queries II

题目大意

给出 \(n\) 个数,\(q\) 次询问,求最大子段和,相同的数只算一次。

分析

看到一个区间内相同的数只能算一次,经验告诉我们要考虑离线

我们将区间按照右端点排序,用pre[i]来表示i上次出现的位置。

接下来,我们来考虑线段树需要维护什么。

首先,我们考虑之前不加条件时,我们维护的值还可以维护嘛?

很显然,不太可行,因为当一个区间出现多个值的时候,我们不知道需要哪个位置的值,而其他的不要。

我们考虑从离线角度思考,我们维护四个值sum,stag,hismax,htag。假设此时是以y为结尾的区间。

  • sum[i]表示从[i,y]的所有值只算一次的和
  • stag表示区间加懒标记
  • hismax[i]表示以i为起点,终点小于t的所有区间的最大值
  • htag历史加懒标记,当多个区间加操作发生时,我们只加其中最大的。

那具体怎么加,才能使得所有值值算一次的和呢?

还记得,我们有一个pre[i]嘛,此时我们直接从[pre[i]+1,i]区间加上w[i]

这样我们能保证,相同的值,不会多次对sum造成影响。

这个思路非常巧妙,我们再来顺一遍。

我们,想要保证一个区间内相同的值只被算一次,同时加上离线。

我们考虑维护sum,同时每次碰到一个节点i,我们区间加[pre[i]+1,i],这样可以保证该值的影响只影响到前面从上一次遇到相同的值的位置的下一个到现在的所有位置。这个消除多个影响的设计在于,如果我们直接维护和,这样就可以通过限定区域来限定影响。同时这个和的设计也很巧妙。其利用了离线的状态去设计了和的状态定义。

具体的一些维护细节,可以直接看代码。

Ac_code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
struct Node
{
    int l,r;
    LL sum,stag,hismax,htag;
}tr[N<<2];
struct Line
{
    int l,r,id;
    bool operator<(const Line& W)const 
    {
        return r<W.r;
    }
}line[N];
int w[N],pos[2*N+10];
LL ans[N];
int n,m;

void push(Node &u,Node &l,Node &r)
{
    u.sum = max(l.sum,r.sum);
    u.hismax = max(l.hismax,r.hismax);
}

void pushup(int u)
{
    push(tr[u],tr[u<<1],tr[u<<1|1]);
}

void pushdown(int u)
{
    auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1];
    left.hismax = max(left.hismax,left.sum+root.htag);//每次只加加序列的最大值
    left.sum += root.stag;
    left.htag = max(left.htag,left.stag+root.htag);//维护累积加序列的最大值
    left.stag += root.stag;
    right.hismax = max(right.hismax,right.sum+root.htag);
    right.sum += root.stag;
    right.htag = max(right.htag,right.stag+root.htag);
    right.stag += root.stag;
    root.stag = root.htag = 0;
}

void build(int u,int l,int r)
{
    tr[u] = {l,r};
    if(l==r) return ;
    int mid = l + r >> 1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}

void modify(int u,int l,int r,int k)
{
    if(l<=tr[u].l&&tr[u].r<=r)
    {
        tr[u].sum += k;
        tr[u].hismax = max(tr[u].hismax,tr[u].sum);
        tr[u].stag += k;
        tr[u].htag = max(tr[u].htag,tr[u].stag);
        return ;
    }
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(l<=mid) modify(u<<1,l,r,k);
    if(r>mid) modify(u<<1|1,l,r,k);
    pushup(u);
}

Node query(int u,int l,int r)
{
    if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(r<=mid) return query(u<<1,l,r);
    else if(l>mid) return query(u<<1|1,l,r);
    else 
    {
        auto left = query(u<<1,l,r);
        auto right = query(u<<1|1,l,r);
        Node res;
        push(res,left,right);
        return res;
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",w+i);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int l,r;scanf("%d%d",&l,&r);
        line[i] = {l,r,i};
    }
    sort(line+1,line+1+m);
    build(1,1,n);
    int idx = 1;
    for(int i=1;i<=m;i++)
    {
        for(int j=idx;j<=line[i].r;j++)
        {
            modify(1,pos[w[j]+N]+1,j,w[j]);
            pos[w[j]+N] = j;
        }
        ans[line[i].id] = query(1,line[i].l,line[i].r).hismax;
        idx = line[i].r + 1;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
    return 0;
}

标签:pre,these,sum,离线,SP1557,II,区间,维护,我们
From: https://www.cnblogs.com/aitejiu/p/16641967.html

相关文章

  • 768. 最多能完成排序的块 II
    题目(链接)arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。我们......
  • 260. 只出现一次的数字 III
     难度中等645收藏分享切换为英文接收动态反馈给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。你可以......
  • FTP的传输有两种方式:ASCII传输模式和二进制数据传输模式
    FTP的传输有两种方式:ASCII传输模式和二进制数据传输模式_boker的博客-CSDN博客_ftp传输二进制 https://blog.csdn.net/z507263441/article/details/38586769FTP的传输有......
  • leetcode-998. 最大二叉树 II
    998.最大二叉树II图床:blogimg/刷题记录/leetcode/998/刷题代码汇总:https://www.cnblogs.com/geaming/p/16428234.html题目思路看到树就要想到递归。解法/***D......
  • 654.最大二叉树+998.最大二叉树II
    654.最大二叉树题目描述给定一个不重复的整数数组 nums。 最大二叉树 可以用下面的算法从 nums递归地构建:创建一个根节点,其值为 nums中的 最大值 。递......
  • 通信协议详解(一):IIC总线协议(传输时序+数据格式+设计实现) - 知乎
    一、IIC(Inter-IntegratedCircuit)介绍    IIC(Inter-IntegratedCircuit)即集成电路总线,它是一种具有两线传输的串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了......
  • CF633H Fibonacci-ish II 莫队 线段树 矩阵
    CF633HFibonacci-ishII题意很简明同时给人以不可做感。直接暴力大概是\(n^2log\)的优化一下提前排好序从小到大枚举数字再枚举询问可以完成\(n^2\)经过精细的优化......
  • Apache与IIS的优劣对比
    对于中小企业来说建立自己的网站,对外展示自己的页面是最平常不过的事情了。目前最流行的建立WWW服务工具就要属Apache与IIS了。那么他们之间都有什么区别呢?到底哪个工具才......
  • 「翻译」SAP制造集成和智能(SAP MII)
    SAP制造集成和智能(SAPMII)  集成和连接是成功的工业4.0计划的关键。SAPManufacturingIntegrationandIntelligence(SAPMII)是集成各种应用程序、设备和传感器并将......
  • 「翻译」SAP MII(SAP制造集成和智能)-灵活且可扩展
    SAPMII(SAP制造集成和智能)-灵活且可扩展    通过SAPMII,SAP提供了一个基于Web的、标准化和灵活的IT平台,用于垂直集成到生产中。这将面向流程的制造单元的生产......