• bzoj4540 序列 (单调栈+莫队+rmq)


    首先,如果我知道[l,r],要转移到[l,r+1]的时候,就是加上以r+1为右端点,[l,r+1]为左端点的区间的最小值,其他情况和这个类似

    考虑这玩意怎么求

    右端点固定的话,我左端点越往左走,这个最小值一定是越来越小

    找到[l,r+1]范围内的最小值mi,那么在mi前面的第一个比mi小的位置(记为L[mi]),一定在这个范围外

    而且相同的左端点,以这个位置为右端点和以r+1为右端点,区间的最小值是相同的(都是这个数)

    所以可以只记f[i]表示以i为右端点,左端点在[1,i]的最小值的和

    再问[l,r+1]的话,那就是f[r+1]-f[L[mi]]再减掉左端点在[L[mi]+1,l-1]这个范围内的,而这些的最小值都是mi

    这个L用单调栈来求,mi用rmq来求

    其他的转移同理

     1 #include<bits/stdc++.h>
     2 #define CLR(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 typedef long long ll;
     5 typedef unsigned long long ull;
     6 typedef pair<int,int> pa;
     7 const int maxn=1e4+10,maxm=1e5+10;
     8 
     9 inline ll rd(){
    10     ll x=0;char c=getchar();int neg=1;
    11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    13     return x*neg;
    14 }
    15 
    16 int N,NN,M,a[maxn];
    17 int stk[maxn],sh;
    18 int L[maxn],R[maxn];
    19 pa rmq[maxn][20];
    20 ll f[maxn],g[maxn];
    21 struct Node{
    22     int l,r,i;
    23 }que[maxm];
    24 ll ans[maxm];
    25 
    26 inline bool cmp(Node a,Node b){
    27     return a.l/NN==b.l/NN?a.r<b.r:a.l<b.l;
    28 }
    29 
    30 inline pa getmin(int l,int r){
    31     int m=log2(r-l+1);
    32     return min(rmq[l][m],rmq[r-(1<<m)+1][m]);
    33 }
    34 
    35 inline void add(ll &n,int i,int bnd,int v){
    36     if(bnd<=i){
    37         pa p=getmin(bnd,i);
    38         n+=v*(f[i]-f[L[p.second]]-1ll*p.first*(bnd-L[p.second]-1));
    39     }else{
    40         pa p=getmin(i,bnd);
    41         n+=v*(g[i]-g[R[p.second]]-1ll*p.first*(R[p.second]-bnd-1));
    42     }
    43 }
    44 
    45 int main(){
    46     //freopen("","r",stdin);
    47     int i,j,k;
    48     N=rd(),M=rd();NN=sqrt(N);
    49     for(i=1;i<=N;i++) a[i]=rd();
    50     for(i=N;i;i--){
    51         rmq[i][0]=make_pair(a[i],i);
    52         for(j=1;(i+(1<<j)-1)<=N;j++)
    53             rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);
    54     }
    55     for(i=1;i<=N;i++){
    56         while(sh&&a[stk[sh]]>a[i]){
    57             R[stk[sh--]]=i;
    58         }stk[++sh]=i;
    59     }sh=0;
    60     for(i=N;i;i--){
    61         while(sh&&a[stk[sh]]>a[i]){
    62             L[stk[sh--]]=i;
    63         }stk[++sh]=i;
    64     }
    65     for(i=1;i<=N;i++){
    66         f[i]=f[L[i]]+1ll*(i-L[i])*a[i];
    67     }
    68     for(i=N;i;i--){
    69         if(!R[i]) R[i]=N+1;
    70         g[i]=g[R[i]]+1ll*(R[i]-i)*a[i];
    71     }
    72     
    73     for(i=1;i<=M;i++){
    74         que[i].l=rd(),que[i].r=rd(),que[i].i=i;
    75     }
    76     sort(que+1,que+M+1,cmp);
    77     int l=1,r=0;ll n=0;
    78     for(i=1;i<=M;i++){
    79         while(r<que[i].r) add(n,++r,l,1);
    80         while(r>que[i].r) add(n,r--,l,-1);
    81         while(l<que[i].l) add(n,l++,r,-1);
    82         while(l>que[i].l) add(n,--l,r,1);
    83         ans[que[i].i]=n;
    84     }
    85     for(i=1;i<=M;i++)
    86         printf("%lld
    ",ans[i]);
    87     return 0;
    88 }
    89 /*
    90 9 2
    91 1 7 5 2 6 4 3 5 8
    92 1 6
    93 3 8
    94 */
  • 相关阅读:
    Java 反射
    类中静态/普通/构造初始化顺序
    计算机世界中的0和1
    Java并发练习
    HashMap底层
    HashMap 与 Hashtable 的区别
    为什么重写了equals() 就要重写hashcode()
    干货型up主
    JSP页面元素
    重定向与请求转发的区别
  • 原文地址:https://www.cnblogs.com/Ressed/p/9997524.html
Copyright © 2020-2023  润新知