• P6406 [COCI2014-2015] Norma 分治+数学


    题意:

    戳这里

    分析:

    • 暴力

    (O(n log n)) 预处理 ST表 然后 (O(n^2)) 枚举左右端点

    • 正解

    我们要优化统计答案的复杂度,也就是说我们需要大概 (O(n log n)) 的复杂度 来统计答案

    很容易想到每一个点作为最大值和最小值的影响是一段区间,那么我们就递归通过分治来统计区间的贡献,和 CDQ 分治的思想差不多,我们只需要统计跨过区间中点的影响,剩下的递归下去

    具体来说,每一次分治中,我们枚举左端点 (i) ,统计以 (i) 为左端点的序列的答案,分三种情况讨论 , 默认 (ple q)

    变量声明:

    mx = $ max(a_idots a_{mid})$ ; mn = $ min(a_idots a_{mid})$

    mna = (sum mn) ; mnb = (sum mn imes i)

    mxa = (sum mx) ; mxb = $sum mx imes i $

    mma = (sum mx imes mn) ; mmb = (sum mx imes mn imes i)

    p 表示满足 (mn leqslant min { a[mid!+!1] cdots a[j] }) 的最大的 p 的位置
    q 表示满足 (mx geqslant max { a[mid!+!1] cdots a[k] }) 的最大的 q 的位置。

    1. (mx,mn) 都取 ([mid+1,p])

    (ans Leftrightarrow sum mn imes mx imes (j-i+1))

    1. (mx)(mn) 不取 ([p,q])

    (ans Leftrightarrow mx imes sum min_j imes (j-i+1))

    1. (mx,mn) 都不取 ([q,r])

    (ansLeftrightarrow sum max_j imes min_j imes (j-i+1))

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
    	inline int read()
    	{
    		int x=0,f=1;char ch=getchar();
    		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    		return x*f;
    	}
    	
    	const int maxn = 5e5+5;
    	const long long mod = 1e9;
    	long long a[maxn],mxa[maxn],mxb[maxn],mna[maxn],mnb[maxn],mma[maxn],mmb[maxn];
    	long long ans,n,mn,mx;
    	
    	void qm(long long x){return (void)(ans=(ans+x>=mod?ans+x-mod:ans+x));}
    	long long S(long long l,long long r){return (long long)(l+r)*(r-l+1)/2%mod;}
    	
    	void solve(int l,int r)
    	{
    		if(l==r){return (void)(qm(a[l]*a[l]%mod));}
    		long long mid=(l+r)>>1;
    		solve(l,mid);solve(mid+1,r);
    		mn=mod;mx=0;
    		mxa[mid]=mxb[mid]=mna[mid]=mnb[mid]=mma[mid]=mmb[mid]=0;
    		for(int j=mid+1;j<=r;j++)
    		{
    			mn=min(mn,a[j]);mx=max(mx,a[j]);
    			mxa[j]=(mxa[j-1]+mx)%mod;
    			mxb[j]=(mxb[j-1]+mx*j%mod)%mod;
    			mna[j]=(mna[j-1]+mn)%mod;
    			mnb[j]=(mnb[j-1]+mn*j%mod)%mod;
    			mma[j]=(mma[j-1]+mn*mx%mod)%mod;
    			mmb[j]=(mmb[j-1]+mn*mx%mod*j%mod)%mod;
    		}
    		mn=mod;mx=0;
    		for(int q=mid+1,p=mid+1,i=mid;i>=l;i--)
    		{
    			mn=min(mn,a[i]);mx=max(mx,a[i]);
    			while(p<=r&&mn<a[p]) p++;
    			while(q<=r&&mx>a[q]) q++;
    			if(p<q)
    			{
    				qm(mn*mx%mod*S(mid-i+2,p-i)%mod);
    				qm((mnb[q-1]-mnb[p-1]+mod)*mx%mod+(1-i+mod)*mx%mod*(mna[q-1]-mna[p-1]+mod)%mod);
    				qm((mmb[r]-mmb[q-1]+mod)%mod+(1-i+mod)%mod*(mma[r]-mma[q-1])%mod);
    			}
    			else
    			{
    				qm(mn*mx%mod*S(mid-i+2,q-i)%mod);
    				qm((mxb[p-1]-mxb[q-1]+mod)*mn%mod+(1-i+mod)*mn%mod*(mxa[p-1]-mxa[q-1]+mod)%mod);
    				qm((mmb[r]-mmb[p-1]+mod)%mod+(1-i+mod)%mod*(mma[r]-mma[p-1]+mod)%mod);
    			} 
    		}
    	}
    	
    	void work()
    	{
    		n=read();
    		for(int i=1;i<=n;i++) a[i]=read();
    		solve(1,n);
    		printf("%lld
    ",ans%mod);
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
    
  • 相关阅读:
    浅析 x1B[1;3;31mxterm.jsx1B[0m 是什么?如何在终端输出带颜色等格式的字符串
    使用xterm报错:Error: Terminal requires a parent element、及删除时报错:xterm.js: Parsing error 的问题
    浅析如何实现浏览器访问远程桌面/服务器界面:NoVNC
    浅析NAS网络存储是什么及其主要用途
    浅析uniapp如何做图片裁剪及遇到问题 uni.canvasToTempFilePath 在APP下返回的是临时路径,如何把路径转为base64的解决方案
    浅析webpack中mode的取值及不同取值的作用/打包方式及摇树优化(tree-shaking)的理解
    P1160 队列安排题解
    P1996 约瑟夫问题题解
    P1449 后缀表达式题解
    P1825 玉米田迷宫题解
  • 原文地址:https://www.cnblogs.com/youth518/p/14050249.html
Copyright © 2020-2023  润新知