• SP1557 GSS2


    传送门

    线段树好题

    因为题目中相同的只算一次,我们可以联想到HH的项链,于是考虑离线的做法

    先把所有的询问按$r$排序,然后每一次不断将$a[r]$加入线段树

    线段树上维护四个值,$sum,hix,sumtag,hixtag$,分别代表当前节点的值,节点历史上的最大值,当前的增加标记,历史上最大的增加标记

    然后pushdown的过程可以看代码,还是比较清楚的

    考虑怎么添加元素,设序列中上一个与$i$相等的数的位置是$Pre[i]$,那么就把区间$[Pre[i],i]$加$a[i]$即可

    查询的话只要查$[l,r]$的$hix$即可

    除了pushdown有点烦其他都还好

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define ls (p<<1)
     6 #define rs (p<<1|1)
     7 #define ll long long
     8 using namespace std;
     9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    10 char buf[1<<21],*p1=buf,*p2=buf;
    11 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    12 ll read(){
    13     #define num ch-'0'
    14     char ch;bool flag=0;ll res;
    15     while(!isdigit(ch=getc()))
    16     (ch=='-')&&(flag=true);
    17     for(res=num;isdigit(ch=getc());res=res*10+num);
    18     (flag)&&(res=-res);
    19     #undef num
    20     return res;
    21 }
    22 char sr[1<<21],z[20];int C=-1,Z;
    23 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    24 void print(ll x){
    25     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    26     while(z[++Z]=x%10+48,x/=10);
    27     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    28 }
    29 const int N=1e5+5;
    30 struct node{
    31     ll sum,hix,stag,htag;
    32     node(){sum=hix=stag=htag=0;}
    33     inline node operator +(node b){
    34         node res;
    35         res.sum=max(sum,b.sum),res.hix=max(hix,b.hix);
    36         return res;
    37     }
    38 }b[N<<2];
    39 struct Q{
    40     int l,r,id;
    41     inline bool operator <(const Q b)const
    42     {return r<b.r;}
    43 }q[N];
    44 int n,m,cur[N*2],Pre[N],ql,qr;ll a[N],ans[N],k;
    45 inline void upd(int p){b[p]=b[ls]+b[rs];}
    46 void pd(int p){
    47     b[ls].hix=max(b[ls].hix,b[ls].sum+b[p].htag);
    48     b[rs].hix=max(b[rs].hix,b[rs].sum+b[p].htag);
    49     b[ls].sum+=b[p].stag,b[rs].sum+=b[p].stag;
    50     b[ls].htag=max(b[ls].htag,b[ls].stag+b[p].htag);
    51     b[rs].htag=max(b[rs].htag,b[rs].stag+b[p].htag);
    52     b[ls].stag+=b[p].stag,b[rs].stag+=b[p].stag;
    53     b[p].stag=b[p].htag=0;
    54 }
    55 void update(int p,int l,int r){
    56     if(ql<=l&&qr>=r){
    57         b[p].sum+=k,cmax(b[p].hix,b[p].sum);
    58         b[p].stag+=k,cmax(b[p].htag,b[p].stag);
    59         return;
    60     }
    61     pd(p);int mid=(l+r)>>1;
    62     if(ql<=mid) update(ls,l,mid);
    63     if(qr>mid) update(rs,mid+1,r);
    64     upd(p);
    65 }
    66 node query(int p,int l,int r){
    67     if(ql<=l&&qr>=r) return b[p];
    68     pd(p);int mid=(l+r)>>1;
    69     if(ql>mid) return query(rs,mid+1,r);
    70     else if(qr<=mid) return query(ls,l,mid);
    71     else return query(ls,l,mid)+query(rs,mid+1,r);
    72 }
    73 int main(){
    74 //    freopen("testdata.in","r",stdin);
    75     n=read();
    76     for(int i=1;i<=n;++i)
    77     a[i]=read(),Pre[i]=cur[a[i]+(int)1e5],cur[a[i]+(int)1e5]=i;
    78     m=read();
    79     for(int i=1;i<=m;++i)
    80     q[i].l=read(),q[i].r=read(),q[i].id=i;
    81     sort(q+1,q+1+m);
    82     for(int i=1,j=1;i<=n&&j<=m;++i){
    83         ql=Pre[i]+1,qr=i,k=a[i];update(1,1,n);
    84         for(;j<=m&&q[j].r<=i;++j){
    85             ql=q[j].l,qr=q[j].r;
    86             ans[q[j].id]=query(1,1,n).hix;
    87         }
    88     }
    89     for(int i=1;i<=m;++i) print(ans[i]);
    90     return Ot(),0;
    91 }
  • 相关阅读:
    测试软件—禅道BUG管理工具
    C语言 线性表的操作~(未完)
    数据库考纲~
    圣杯布局和双飞翼布局总局
    总结布局用法
    springboot~入门第三篇~与mybatis整合~(未完)
    微信小程序里 wx:for和wx:for-item区别(补充下wx:key)
    对比下小程序语法和Vue语法异同
    视频转换 rtsp 流 转rtmp流播放(待完善)
    Vue钩子函数~
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9826321.html
Copyright © 2020-2023  润新知