• BZOJ3745 : [Coci2014]Norma


    考虑枚举右端点,用线段树维护[i,nowr]的答案。

    当右端点向右延伸时,需要知道它前面第一个比它大/小的数的位置,这里面的最值将发生改变,这个使用单调队列求出,然后将所有的l都加1。

    注意常数优化。

    #include<cstdio>
    #define PB int mid=(a+b)>>1,l=x<<1,r=l|1;if(T[x].tx)cmax1(l,T[x].tx),cmax1(r,T[x].tx),T[x].tx=0;if(T[x].tn)cmin1(l,T[x].tn),cmin1(r,T[x].tn),T[x].tn=0;if(T[x].tl)clen1(l,T[x].tl),clen1(r,T[x].tl),T[x].tl=0;
    #define UP T[x].sx=(T[l].sx+T[r].sx)%P;T[x].sn=(T[l].sn+T[r].sn)%P;T[x].sl=(T[l].sl+T[r].sl)%P;T[x].sxn=(T[l].sxn+T[r].sxn)%P;T[x].sxl=(T[l].sxl+T[r].sxl)%P;T[x].snl=(T[l].snl+T[r].snl)%P;T[x].sxnl=(T[l].sxnl+T[r].sxnl)%P;
    typedef long long ll;
    const int N=500010,P=1000000000;
    int n,i,v[N],q1[N],q2[N],t1,t2,ans;
    struct node{int sx,sn,sl,sxn,sxl,snl,sxnl,tx,tn,tl,l;}T[1050000];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    void build(int x,int a,int b){
      T[x].l=b-a+1;
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    inline void cmax1(int x,ll p){
      T[x].sx=p*T[x].l%P;
      T[x].sxn=p*T[x].sn%P;
      T[x].sxl=p*T[x].sl%P;
      T[x].sxnl=p*T[x].snl%P;
      T[x].tx=p;
    }
    inline void cmin1(int x,ll p){
      T[x].sn=p*T[x].l%P;
      T[x].sxn=p*T[x].sx%P;
      T[x].snl=p*T[x].sl%P;
      T[x].sxnl=p*T[x].sxl%P;
      T[x].tn=p;
    }
    inline void clen1(int x,ll p){
      T[x].sl=(p*T[x].l+T[x].sl)%P;
      T[x].sxl=(p*T[x].sx+T[x].sxl)%P;
      T[x].snl=(p*T[x].sn+T[x].snl)%P;
      T[x].sxnl=(p*T[x].sxn+T[x].sxnl)%P;
      T[x].tl=(T[x].tl+p)%P;
    }
    void cmax(int x,int a,int b,int c){
      if(c<=a&&b<=i){cmax1(x,v[i]);return;}
      PB
      if(c<=mid)cmax(l,a,mid,c);
      if(i>mid)cmax(r,mid+1,b,c);
      UP
    }
    void cmin(int x,int a,int b,int c){
      if(c<=a&&b<=i){cmin1(x,v[i]);return;}
      PB
      if(c<=mid)cmin(l,a,mid,c);
      if(i>mid)cmin(r,mid+1,b,c);
      UP
    }
    void clen(int x,int a,int b){
      if(b<=i){clen1(x,1);return;}
      PB
      clen(l,a,mid);
      if(i>mid)clen(r,mid+1,b);
      UP
    }
    int main(){
      read(n);
      for(i=1;i<=n;i++)read(v[i]);
      build(1,1,n);
      for(i=1;i<=n;q1[++t1]=q2[++t2]=i++){
        while(t1&&v[q1[t1]]<v[i])t1--;
        while(t2&&v[q2[t2]]>v[i])t2--;
        cmax(1,1,n,q1[t1]+1),cmin(1,1,n,q2[t2]+1),clen(1,1,n);
        ans=(ans+T[1].sxnl)%P;
      }
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    自己动手制作symbian签名
    中移动陈大庆:中国移动JAVA4.1规范和SDK工具
    角色扮演游戏引擎的设计原理
    小团队开发J2ME游戏的阶段划分
    角色扮演游戏中敌人AI(人工智能)的设计方法
    入门:Android 文档的阅读顺序
    2016 MultiUniversity Training Contest 1
    真我
    DBA是我的梦想
    解决VS2010自带的C/C++编译器CL找不到mspdb100.dll的问题
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403205.html
Copyright © 2020-2023  润新知