• BZOJ4262 : Sum


    最大值和最小值的问题是独立且相似的,考虑最大值:

    考虑离线,设ask(i,l,r)为以1到i为右端点时左端点在区间[l,r]内的区间最大值的和。

    从1到n枚举右端点,假设现在是i,那么可以通过单调栈求出最小的j使得[j,i]内a[i]是最大值。

    然后左端点在[j,i]区间内的所有区间最大值都应当变为a[i],且所有答案应该加上本身的值。

    通过线段树打标记维护,时间复杂度$O(nlog n)$。

    对于线段树上每个节点,维护以下信息:

    v : 区间内所有数的和

    s : 历史上所有v的和

    l : 区间长度

    a,b,c,d : 标记,分别表示生效之后

    v'=a*v+b*l

    s'=c*v+d*l+s

    #include<cstdio>
    #include<algorithm>
    #define N 262150
    typedef long long ll;
    int n,m,i,j,l1,r1,l2,r2,a[N],q[N],t,cnt;ll t1,t2,ans[N];
    struct Q{
      int i,l,r,p,t;
      Q(){}
      Q(int _i,int _l,int _r,int _p,int _t){i=_i,l=_l,r=_r,p=_p,t=_t;}
    }b[N];
    inline bool cmp(const Q&a,const Q&b){return a.i<b.i;}
    struct tag{
      ll a,b,c,d;
      tag(){a=1,b=c=d=0;}
      tag(ll _a,ll _b,ll _c,ll _d){a=_a,b=_b,c=_c,d=_d;}
      inline bool ex(){return a!=1||b||c||d;}
      inline tag operator+(const tag&B){
        return tag(a*B.a,b*B.a+B.b,a*B.c+c,d+b*B.c+B.d);
      }
    }tmp;
    struct Node{ll v,s;int l;tag t;}T[N];
    inline void add1(int x,tag p){
      T[x].s+=p.c*T[x].v+p.d*T[x].l;
      T[x].v=p.a*T[x].v+p.b*T[x].l;
      T[x].t=T[x].t+p;
    }
    inline void pb(int x){
      if(T[x].t.ex()){
        add1(x<<1,T[x].t);
        add1(x<<1|1,T[x].t);
        T[x].t=tag();
      }
    }
    inline void up(int x){
      T[x].v=T[x<<1].v+T[x<<1|1].v;
      T[x].s=T[x<<1].s+T[x<<1|1].s;
    }
    void build(int x,int a,int b){
      T[x].v=T[x].s=0,T[x].l=b-a+1,T[x].t=tag();
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void add(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){add1(x,tmp);return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)add(x<<1,a,mid,c,d);
      if(d>mid)add(x<<1|1,mid+1,b,c,d);
      up(x);
    }
    ll ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return T[x].s;
      pb(x);
      int mid=(a+b)>>1;ll t=0;
      if(c<=mid)t=ask(x<<1,a,mid,c,d);
      if(d>mid)t+=ask(x<<1|1,mid+1,b,c,d);
      return up(x),t;
    }
    int main(){
      for(scanf("%d",&m);i<m;i++){
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        if(l2>1)b[++cnt]=Q(l2-1,l1,r1,i,-1);
        b[++cnt]=Q(r2,l1,r1,i,1);
        if(n<r1)n=r1;
        if(n<r2)n=r2;
      }
      std::sort(b+1,b+cnt+1,cmp);
      for(t1=1023,t2=1025,i=1;i<=n;i++,t1=t1*1023%1000000000,t2=t2*1025%1000000000)a[i]=t1^t2;
      for(build(1,1,n),i=j=1;i<=n;q[++t]=i++){
        while(t&&a[q[t]]<a[i])t--;
        tmp=tag(0,a[i],0,0),add(1,1,n,q[t]+1,i),add1(1,tag(1,0,1,0));
        while(j<=cnt&&b[j].i==i)ans[b[j].p]+=ask(1,1,n,b[j].l,b[j].r)*b[j].t,j++;
      }
      for(build(1,1,n),t=0,i=j=1;i<=n;q[++t]=i++){
        while(t&&a[q[t]]>a[i])t--;
        tmp=tag(0,a[i],0,0),add(1,1,n,q[t]+1,i),add1(1,tag(1,0,1,0));
        while(j<=cnt&&b[j].i==i)ans[b[j].p]-=ask(1,1,n,b[j].l,b[j].r)*b[j].t,j++;
      }
      for(i=0;i<m;i++)printf("%lld
    ",ans[i]);
      return 0;
    }
    

      

  • 相关阅读:
    java拦截器与过滤器打印请求url与参数
    mybatis学习笔记(六)使用generator生成mybatis基础配置代码和目录结构
    【IDEA】IDEA创建Maven的Web项目并运行以及打包
    【环境变量】Linux 下三种方式设置环境变量与获取环境变量
    【Git】GitHub的SSH提交配置[
    spring配置redis注解缓存
    【查看linux配置】查看linux系统常用的命令,Linux查看系统配置常用命令
    Redis集群
    linux中wget 、apt-get、yum rpm区别
    spring+redis的集成,redis做缓存
  • 原文地址:https://www.cnblogs.com/clrs97/p/4824806.html
Copyright © 2020-2023  润新知