zoukankan      html  css  js  c++  java
  • bzoj 3745: [Coci2015]Norma

    Description

    给定序列(a_i)

    [sum_{i=1}^n sum_{j=i}^n (j-i+1)max{a_i,a_{i+1}cdots a_j}min{a_i,a_{i+1}cdots a_j} ]

    Input

    第1行,一个整数N;
    第2~n+1行,每行一个整数表示序列a。

    Output

    输出答案对10^9取模后的结果。

    Sample Input

    4
    2 4 1 4
    Sample Output

    109

    【数据范围】

    (N le 500000)
    (1 le a_i le 10^8)


    我还有什么话可以说呢,都是细节问题。细节什么的最讨厌了
    维护前缀(sum1,sum2,sum3)分别是([0])里记录前缀中每一个数的(a_i*i)后的和,([1])里记录每一个数在区间里的前缀和,这样求一个区间的贡献可以表示成(sum[i][0]-sum[i][1]*j)

    (j)是当前点的编号,于是这样玄学的复杂度>_<

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define ll long long 
    inline ll read(){
    	ll an=0;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){ch=getchar();}
    	while('0'<=ch&&ch<='9'){an=an*10+(ch^48);ch=getchar();}
    	return an;
    }
    const ll mod=1e9;
    const ll MAXn=500000+2333;
    ll ans;
    ll n;
    ll sum1[MAXn][2],sum2[MAXn][2],sum3[MAXn][3],a[MAXn];
    /*
    sum_{i=1}^nsum_{j=i}^n(j-i+1)
    MAX{a_i,a_{i+1}cdots a_j}
    MIN{a_i,a_{i+1}cdots a_j}
    */
    inline void prepare(){
    	n=read();
    	for(ll i=1;i<=n;i++)a[i]=read();
    }
    inline void solve(ll l,ll r){
    	ll mid=l+r>>1;
    	if(l==r){
    		ans=(ans%mod+a[l]*a[l]%mod)%mod;
    		return;
    	}
    	sum1[mid][0]=sum1[mid][1]=0;
    	sum2[mid][0]=sum2[mid][1]=0;
    	sum3[mid][0]=sum3[mid][1]=0;
    	ll ma=-1,mi=1e9;
    	for(ll i=mid+1;i<=r;i++){
    		ma=max(ma,a[i]);
    		mi=min(mi,a[i]);
    		sum1[i][0]=ma%mod*mi%mod*i%mod;
    		sum1[i][1]=ma*mi%mod;
    		sum2[i][0]=mi*i%mod;sum2[i][1]=mi;
    		sum3[i][0]=ma*i%mod;sum3[i][1]=ma;
    		sum1[i][0]=(sum1[i][0]+sum1[i-1][0])%mod;
    		sum1[i][1]=(sum1[i][1]+sum1[i-1][1])%mod;
    		sum2[i][0]=(sum2[i][0]+sum2[i-1][0])%mod;
    		sum2[i][1]=(sum2[i][1]+sum2[i-1][1])%mod;
    		sum3[i][0]=(sum3[i][0]+sum3[i-1][0])%mod;
    		sum3[i][1]=(sum3[i][1]+sum3[i-1][1])%mod;
    	}
    	ma=-1,mi=1e9;
    	ll t1=a[mid+1],t2=a[mid+1];
    	ll p1=mid,p2=mid;
    	for(ll i=mid;i>=l;i--){
    		ma=max(ma,a[i]);
    		mi=min(a[i],mi);
    		while(t1>=mi&&p1<r)p1++,t1=min(t1,a[p1+1]);
    		while(t2<=ma&&p2<r)p2++,t2=max(t2,a[p2+1]);
    		ll tmp;
    		tmp=min(p1,p2);
    		ll wi=(mid+2-i+tmp-i+1)*(tmp-mid)/2;
    		ans=(ans+wi%mod*ma%mod*mi)%mod;
    		tmp=max(p1,p2)+1;
    		wi=sum1[r][0]-sum1[tmp-1][0];
    		wi=(wi-(sum1[r][1]-sum1[tmp-1][1])%mod*(i-1))%mod;
    		ans=(ans%mod+wi)%mod;
    		if(p1<=p2){
    			wi=(sum2[p2][0]-sum2[p1][0])%mod*ma%mod;
    			wi=(wi-(sum2[p2][1]-sum2[p1][1])%mod*(i-1)%mod*ma+mod)%mod;
    			ans=(ans+wi)%mod;
    		}
    		else{
    			wi=(sum3[p1][0]-sum3[p2][0])%mod*mi;
    			wi=(wi-(sum3[p1][1]-sum3[p2][1])%mod*(i-1)%mod*mi%mod+mod)%mod;
    			ans=(ans+wi)%mod;
    		}
    	}
    	solve(l,mid);
    	solve(mid+1,r);
    	ans=(ans%mod+mod)%mod;
    }
    int main(){
    	prepare();
    	solve(1,n);
    	cout<<ans<<"
    ";
    	return 0;
    }
    

  • 相关阅读:
    codeforces 616B Dinner with Emma
    codeforces 616A Comparing Two Long Integers
    codeforces 615C Running Track
    codeforces 612C Replace To Make Regular Bracket Sequence
    codeforces 612B HDD is Outdated Technology
    重写父类中的成员属性
    子类继承父类
    访问修饰符
    方法的参数
    实例化类
  • 原文地址:https://www.cnblogs.com/ck666/p/8067774.html
Copyright © 2011-2022 走看看