bzoj 3745: [Coci2015]Norma【分治】

参考:https://blog.csdn.net/lych_cys/article/details/51203960

真的不擅长这种……

分治,对于一个(l,r),先递归求出(l,mid),(mid+1,r),然后这个区间对答案贡献的就是经过mid的区间

我们先预处理出mid为l的右端点的mx*mn*len的前缀和与mx*mn的前缀和,然后枚举左端点,右端点维护两个下标j,k,分别表示mn和mx在左端点时的合法右端点

然后分三种情况处理,假设j<k

1.右端点在(mid+1,j)时,直接计算

2.右端点在(j,k)时,相当于最小值在j,最大值在(j,k),预处理一个前缀和来计算

3.右端点在(k,r)时,直接用预处理的前缀和处理,要减去右端点在(mid+1,j)时的情况

#include<iostream>
#include<cstdio>
using namespace std;
const int N=500005,mod=1e9;
int n,ans,a[N],c[N][2],f[N],g[N],p[N][2],q[N][2];
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if(p==‘-‘)
            f=-1;
        p=getchar();
    }
    while(p>=‘0‘&&p<=‘9‘)
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
void jia(int &x,int y)
{
    x+=y;
    x>=mod?x-=mod:0;
}
void jian(int &x,int y)
{
    x-=y;
    x<0?x+=mod:0;
}
int clc(int x,int y)
{
    return 1ll*(x+y)*(y-x+1)/2%mod;
}
void wk(int l,int r)
{
    if(l==r)
    {
        jia(ans,1ll*a[l]*a[l]%mod);
        return;
    }
    int mid=(l+r)>>1;
    wk(l,mid);
    wk(mid+1,r);
    c[mid][0]=c[mid][1]=a[mid];
    for(int i=mid-1;i>=l;i--)
        c[i][0]=min(c[i+1][0],a[i]),c[i][1]=max(c[i+1][1],a[i]);
    int mn=1e9,mx=-1e9;
    f[mid]=g[mid]=p[mid][0]=p[mid][1]=q[mid][0]=q[mid][1]=0;
    for(int i=mid+1;i<=r;i++)
    {
        mn=min(mn,a[i]),mx=max(mx,a[i]);
        f[i]=1ll*mn*mx%mod*(i-mid)%mod;
        jia(f[i],f[i-1]);
        g[i]=1ll*mn*mx%mod;
        jia(g[i],g[i-1]);
        p[i][0]=(p[i-1][0]+mn)%mod;
        q[i][0]=(q[i-1][0]+mx)%mod;
        p[i][1]=1ll*mn*(i-mid)%mod;
        jia(p[i][1],p[i-1][1]);
        q[i][1]=1ll*mx*(i-mid)%mod;
        jia(q[i][1],q[i-1][1]);
    }
    for(int i=mid,j=mid,k=mid;i>=l;i--)
    {
        while(j<r&&c[i][0]<a[j+1])
            j++;
        while(k<r&&c[i][1]>a[k+1])
            k++;
        jia(ans,1ll*c[i][0]*c[i][1]%mod*clc(mid-i+2,min(j,k)-i+1)%mod);
        jia(ans,(1ll*g[r]*(mid-i+1)+f[r])%mod);
        jian(ans,(1ll*g[max(j,k)]*(mid-i+1)+f[max(j,k)])%mod);
        if(j<k)
        {
            jia(ans,(1ll*p[k][0]*(mid-i+1)+p[k][1])%mod*c[i][1]%mod);
            jian(ans,(1ll*p[j][0]*(mid-i+1)+p[j][1])%mod*c[i][1]%mod);
        }
        else
        {
            jia(ans,(1ll*q[j][0]*(mid-i+1)+q[j][1])%mod*c[i][0]%mod);
            jian(ans,(1ll*q[k][0]*(mid-i+1)+q[k][1])%mod*c[i][0]%mod);
        }
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    wk(1,n);
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/9803071.html

时间: 2024-09-27 04:35:25

bzoj 3745: [Coci2015]Norma【分治】的相关文章

bzoj 3745 [Coci2015]Norma——序列分治

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3745 如果分治,就能在本层仅算过 mid 的区间了. 可以从中间到左边地遍历左边,给右边两个指针,表示第一个更新左边造成的最小值/最大值的位置. 两个位置共同的左边可以公式算长度,用左边的最值算:两个位置共同的右边可以预处理,处理出 算上长度(相对mid的)的最值乘积求和 与 不算长度的最值乘积求和(都是前缀),把前者加到答案里,后者乘上左边到mid的长度加到答案里即可:两个位置夹着的位置

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\) \

[BZOJ3745][COCI2015]Norma(分治)

3745: [Coci2015]Norma Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 563  Solved: 249[Submit][Status][Discuss] Description Input 第1行,一个整数N: 第2~n+1行,每行一个整数表示序列a. Output 输出答案对10^9取模后的结果. Sample Input 4 2 4 1 4 Sample Output 109 [数据范围] N <= 500000 1 <=

【BZOJ3745】[Coci2015]Norma cdq分治

[BZOJ3745][Coci2015]Norma Description Input 第1行,一个整数N: 第2~n+1行,每行一个整数表示序列a. Output 输出答案对10^9取模后的结果. Sample Input 4 2 4 1 4 Sample Output 109 [数据范围] N <= 500000 1 <= a_i <= 10^8 题解:最近做这种题好像有点多啊~(虽然我基本上都没A). 比较直接的想法就是找出区间的最大值mid,然后分治处理[l,mid-1]和[mi

BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N行,每

bzoj 3672 购票 点分治+dp

3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1177  Solved: 562[Submit][Status][Discuss] Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接.为了方便起见,我们将全国的 n 个城市用 1 到 n 的整数编号.

BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包

题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或者留言我. 首先这道题能推出个表达式 f[i]代表第i天最大收益. xx[i]表示将第i天的钱都买A的数量 yy[i]表示将第i天的钱都买B的数量 所以f[i]=max(f[i?1],p[i].a?xx[j]+p[i].b?yy[j])j<i 所以我们要维护这个n^2的递推式 又知道f[i]是由小于

BZOJ 3745

分治..... 之前就了解过这种分治统计答案的算法,对于当前的区间[l,r],我们考虑过中间的那条线的区间,这种题往往都存在单调性,我们发现min和max都是随位置单调的,我们枚举左端点x,然后维护两个指针p1,p2,表示[mid+1,p1/p2]这个区间的最值大于/小于[x,mid]的最值的最远的p1/p2,那么答案就可以分3段统计,一段是[mid+1,min(p1,p2)],右端点在这一部分的区间的min和max都一样,比较容易求出.另一段是[max(p1,p2)+1,r],在这一部分的区间

BZOJ 2141: 排队 CDQ分治+bit

2141: 排队 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观.设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量.幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度.为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序