zoukankan      html  css  js  c++  java
  • [SPOJ22343] Norma

    Description

    现在有一个长度为(N(Nleq 500000))的序列,定义区间([l,r])的价值为([l,r])的最小值乘上([l,r])的最大值乘上([l,r])的长度。问这个序列的所有区间的价值和对(10^9)取模的结果。

    Solution

    遇到神仙题考虑分治。

    考虑所有经过(mid)的区间。

    对于小于等于(mid的)(i),我们要求所有在(mid)右边的(j)并计算([i,j])的价值。

    可以先维护出来([i,mid])的最小值和最大值记为(minn,maxn)

    在右边维护两个指针(p,q),分别表示第一个大于(minn)的位置和第一个小于(maxn)的位置。

    如果我们把(i)(mid)倒序循环到(l),那么可以发现,(maxn,minn,p,q)都是具有单调性的。

    那对于一个(i)的答案就可以分成三部分计算(假设(p<q)) :([mid+1,p),[p,q),[q,r])。做几个前缀和弄一下就行了。

    Code

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<cctype>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define int long long
    using std::min;
    using std::max;
    using std::swap;
    using std::vector;
    const int N=5e5+5;
    typedef double db;
    const int mod=1e9;
    typedef long long ll;
    #define pb(A) push_back(A)
    #define pii std::pair<int,int>
    #define mp(A,B) std::make_pair(A,B)
    
    int n;
    ll qz[N][2];
    ll mn[N][2];
    ll mx[N][2];
    ll val[N],ans;
    int stk[N],top;
    
    int qh(int l,int r){
    	if(l>r) return 0;
    	int len=r-l+1;
    	return (l+r)*len/2%mod;
    }
    
    int getint(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while( isdigit(ch))X=X*10+ch-48,ch=getchar();
        if(w) return -X;return X;
    }
    const int inf=1e9;
    void solve(int l,int r){
        if(l==r){(ans+=val[l]*val[l]%mod)%=mod;return;}
        int mid=l+r>>1;
        solve(l,mid);solve(mid+1,r);
        ll minn=inf,maxn=-inf;
        qz[mid][0]=qz[mid][1]=0;
        for(int i=mid+1;i<=r;i++){
            minn=min(minn,val[i]);
            maxn=max(maxn,val[i]);
            mn[i][0]=(mn[i-1][0]+minn)%mod;
            mn[i][1]=(mn[i-1][1]+minn*(i-mid)%mod)%mod;
            mx[i][0]=(mx[i-1][0]+maxn)%mod;
            mx[i][1]=(mx[i-1][1]+maxn*(i-mid)%mod)%mod;
            qz[i][0]=(qz[i-1][0]+(ll)minn*maxn%mod)%mod;
            qz[i][1]=(qz[i-1][1]+(ll)minn*maxn%mod*(i-mid)%mod)%mod;
        }
        minn=inf,maxn=-inf;
        int p=mid+1,q=mid+1;
        for(int i=mid;i>=l;i--){
            minn=min(minn,val[i]);
            maxn=max(maxn,val[i]);
            while(p<=r and val[p]>=minn) p++;
            while(q<=r and val[q]<=maxn) q++;
            int lll=min(p,q),rr=max(p,q);
            int len=lll-mid-1;
            (ans+=qh(mid+1-i+1,lll-1-i+1)*maxn%mod*minn%mod)%=mod;
            if(p<q) (ans+=(mn[q-1][1]-mn[p-1][1]+mod)%mod*maxn%mod+(mn[q-1][0]-mn[p-1][0]+mod)%mod*(mid-i+1)%mod*maxn%mod)%=mod;
            if(p>q) (ans+=(mx[p-1][1]-mx[q-1][1]+mod)%mod*minn%mod	+(mx[p-1][0]-mx[q-1][0]+mod)%mod*(mid-i+1)%mod*minn%mod)%=mod;
            (ans+=(qz[r][1]-qz[rr-1][1]+mod)%mod+(qz[r][0]-qz[rr-1][0]+mod)%mod*(mid-i+1)%mod)%=mod;
        }
    }
    
    signed main(){
        n=getint();
        for(int i=1;i<=n;i++) val[i]=getint();
        solve(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Martix工作室考核题 —— 打印一个菱形
    Martix工作室考核题 —— 打印一个菱形
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第一题
    fiddler模拟发送post请求
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/9806821.html
Copyright © 2011-2022 走看看