zoukankan      html  css  js  c++  java
  • SP1557 GSS2 Can you answer these queries II

    XIV.SP1557 GSS2 - Can you answer these queries II

    我认为这是GSS题目中难度最大的一道,不接受反驳。

    这题中出现多次的只给算一次,应该咋办呢?

    我们回忆起这种情况的经典老题:[SDOI2009]HH的项链。正解是将询问离线后按照右端点递增排序,然后出现多次的,就只计算从最后一次出现的位置到当前这个位置这段区间的贡献。

    于是本题也可以类似地做。

    我们仍然按照右端点递增顺序枚举,设当前右端点为\(i\)。我们维护对于每个位置\(j\),子段\([j,i]\)的和,设为\(s_j\)。则当\(i\)\(i-1\)移动到\(i\)时,区间\([las_{a_i}+1,i]\)中的所有\(s_j\)都会被增加\(a_i\)。于是我们可以用线段树维护\(s\)数组。

    则我们发现,对于一次询问\([l,r]\),我们只需要求出当\(i=r\)时,区间\([l,r]\)中的历史最大值即可。

    我们考虑对于线段树上每个节点维护这样一些东西:

    • \(mx\),它为区间中当前所有\(s_i\)的最大值。

    • \(MX\),它为区间中历史\(s_i\)的最大值。

    • \(tag\),它为区间的懒标记。

    • \(TAG\),它为从上次pushdown以来,\(tag\)的最大值。

    当我们修改一个位置的值的时候:

    • \(mx\)增加这对应的值;

    • \(tag\)增加对应的值;

    • \(MX\)与当前\(mx\)\(\max\)

    • \(TAG\)与当前\(tag\)\(\max\)

    当我们pushdown的时候:

    • 子节点的\(MX\)\(mx_{son}+TAG_{fa}\)\(\max\)

    • 子节点的\(TAG\)\(tag_{son}+TAG_{fa}\)\(\max\)

    • 之后,子节点的\(mx\)\(tag\)正常地更新。

    • 然后,父节点的\(tag\)\(TAG\)清空。

    我们可以把这俩玩意轻松地二合一:

    void ADD(int x,int y,int z=0){z=max(z,y),seg[x].MX=max(seg[x].MX,seg[x].mx+z),seg[x].TAG=max(seg[x].TAG,seg[x].tag+z),seg[x].mx+=y,seg[x].tag+=y;}

    询问的时候,就直接返回对应区间的\(MX\)即可。

    时间复杂度\(O(n\log n)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m,a[100100],res[100100];
    map<int,int>mp;
    struct Query{
    	int l,r,id;
    	friend bool operator <(const Query &x,const Query &y){
    		return x.r<y.r;
    	}
    }q[100100];
    #define lson x<<1
    #define rson x<<1|1
    #define mid ((l+r)>>1) 
    struct SegTree{
    	ll mx,tag,MX,TAG;//mx:the current maximum in the section; MX:the history maximum in the section; tag:the lazy tag for mx; TAG:the lazy tag for MX
    }seg[400100];
    void ADD(int x,int y,int z=0){z=max(z,y),seg[x].MX=max(seg[x].MX,seg[x].mx+z),seg[x].TAG=max(seg[x].TAG,seg[x].tag+z),seg[x].mx+=y,seg[x].tag+=y;}
    #define pushdown(x) ADD(lson,seg[x].tag,seg[x].TAG),ADD(rson,seg[x].tag,seg[x].TAG),seg[x].tag=seg[x].TAG=0
    #define pushup(x) seg[x].mx=max(seg[lson].mx,seg[rson].mx),seg[x].MX=max(seg[lson].MX,seg[rson].MX)
    void modify(int x,int l,int r,int L,int R,int val){
    	if(l>R||r<L)return;
    	if(L<=l&&r<=R){ADD(x,val);return;}
    	pushdown(x),modify(lson,l,mid,L,R,val),modify(rson,mid+1,r,L,R,val),pushup(x);
    }
    int query(int x,int l,int r,int L,int R){
    	if(l>R||r<L)return 0;
    	if(L<=l&&r<=R)return seg[x].MX;
    	pushdown(x);
    	return max(query(lson,l,mid,L,R),query(rson,mid+1,r,L,R));
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	scanf("%d",&m);
    	for(int i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
    	sort(q+1,q+m+1);
    	for(int i=1,j=1;i<=n;i++){
    		modify(1,1,n,mp[a[i]]+1,i,a[i]),mp[a[i]]=i;
    		while(j<=m&&q[j].r<=i)res[q[j].id]=query(1,1,n,q[j].l,q[j].r),j++;
    	}
    	for(int i=1;i<=m;i++)printf("%d\n",res[i]);
    	return 0;
    }
    

  • 相关阅读:
    regasm.exe程序集注册工具
    C#获取CPU温度
    检测已连接显示器
    防火墙规则修改
    WPF中播放声音
    python获取火狐浏览器的历史记录
    python学习-[小甲鱼]零基础入门教学
    推荐一些常用感觉不错的jQuery插件
    HTML5本地存储 Web Storage
    Javascript模块化开发,使用模块化脚本加载工具RequireJS,提高你代码的速度和质量。
  • 原文地址:https://www.cnblogs.com/Troverld/p/14611256.html
Copyright © 2011-2022 走看看