【2020.11.17提高组模拟】数数(cuvelia) 题解

题目描述

给你一个长度为n的序列\(a_1...a_n\)。对于所有的\(k\in [1,n]\)选择序列中的\(k\)个数(下标为\(i_1,i_2...i_k\)),使得\(\sum_{l=1}^k\sum_{r=l}^k|a_{i_l}-a_{i_r}|\)最大,并对于每个\(k\)求出这个最大值。

\(n\le 3\times 10^5\)。

\(|a_i|\le 10^6\)

题意分析

求从一个序列中有序地取出k个数后的最大值,该值为每个数减去其前面所有数的绝对值之和。

首先对原序列排序。排序不影响答案。

接着,显然取出最大和最小值一定没错的。

再依次从没有取出的数中,取最小的和最大的放在取出的序列中间。

这个又为什么是对的呢?

考虑现在要取出的数放到取出的序列中间时,左右各有\(lsize\),\(rsize\)个数,左右数字和各为\(lsum\),\(rsum\)。

那么插入这个数\(x\)对答案的贡献为

\[(rsum-rsize*x)+(lsize*sum-lsum)
\]

提取

\[(rsum-lsum)-(rsize-lsize)*x
\]

这个式子同时解释了为什么整个取出序列必须时升序的,且要从最大值和最小值开始取数,以及为什么要尽量保持左右数的数量平均。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define debug printf("Now is %d\n",__LINE__);
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
LL a[1000010];
LL ansxb[1000][1000];
LL ans[1000];
int n;
int main()
{
freopen("cuvelia.in","r",stdin);
freopen("cuvelia.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) a[i]=read();
sort(a+1,a+n+1);
if(n<=5)
{
do
{
re LL now=0;
for(re int i=1;i<=n;i++)
{
for(re int j=1;j<=i;j++) now+=abs(a[i]-a[j]);
if(now>ans[i])
{
ans[i]=now;
for(int j=1;j<=i;j++) ansxb[i][j]=a[j];
}
}
}while(next_permutation(a+1,a+n+1));
for(re int i=1;i<=n;i++)
{
cout<<ans[i]<<endl;
// cout<<i<<":"<<ans[i]<<" = ";
// for(re int j=1;j<=i;j++)
// {
// cout<<ansxb[i][j]<<" ";
// }
// cout<<endl;
}
}
else
{
cout<<0<<endl;
LL ans=a[n]-a[1];
LL l=2,r=n-1,lsum=a[1],lsize=1,rsum=a[n],rsize=1;
cout<<ans<<endl;
for(re int i=3;i<=n;i++)
{
if(i&1)
{
ans+=rsum-rsize*a[l]-lsum+lsize*a[l];
lsum+=a[l];
lsize++;
l++;
}
else
{
ans+=rsum-rsize*a[r]-lsum+lsize*a[r];
rsum+=a[r];
rsize++;
r--;
}
write(ans);
}
}
return 0;
}

结语

考试的时候不知道为什么脑子抽到了,用了\(cout\)来输出这\(3*10^5\)个答案。

然后就

\[100\Rightarrow70\\
Rank19\Rightarrow36
\]

好耶!(

【2020.11.17提高组模拟】数数(cuvelia) 题解的更多相关文章

  1. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  2. 【2020.11.28提高组模拟】T2 序列(array)

    序列(array) 题目描述 ​给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...

  3. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  4. 【2020.11.30提高组模拟】删边(delete)

    删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...

  5. JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)

    题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...

  6. JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)

    题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...

  7. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  8. 11.5NOIP2018提高组模拟题

    书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...

  9. 【2020.12.01提高组模拟】A组反思

    105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...

  10. 【2020.12.02提高组模拟】球员(player)

    题目 题目描述 老师们已经知道学生喜欢睡觉,Soaring是这项记录保持者.他只会在吃饭或玩FIFA20时才会醒来.因此,他经常做关于足球的梦,在他最近的一次梦中,他发现自己成了皇家马德里足球俱乐部的 ...

随机推荐

  1. 分享一个 Win11 隐藏右下角日期时间的解决方案

    分享一个 Win11 隐藏右下角日期时间的解决方案

  2. linux的zip命令详解 | Linux文件打包成Zip的命令和方法

    zip 命令用来压缩文件 参数: -A:调整可执行的自动解压缩文件: -b<工作目录>:指定暂时存放文件的目录: -c:替每个被压缩的文件加上注释: -d:从压缩文件内删除指定的文件: - ...

  3. 运维 —— IMP-00030: failed to create file import_sys for write

    IMP-00030: failed to create file import_sys for writeIMP-00000: Import terminated unsuccessfully原因:操 ...

  4. oracle 数据库服务名怎么查

    WINDOWS上,直接看 服务里的 服务名就好:Oracle SID Service ,中间的SID就是数据库服务的名称.LINUX系统下,输入env |grep SID 可以查看到,一般没换都是这个 ...

  5. llamacpp转换hf、vllm运行gguf

    Linux通过huggingface安装大模型 huggingface官网 https://huggingface.co/ wget https://repo.anaconda.com/minicon ...

  6. AspNetCore MVC 跨域

    通过XMLHttpRequest或者ajax去请求一个AspNetCore API接口服务时,Firefox提示我 已拦截跨源请求:同源策略禁止读取位于 http://localhost:33694/ ...

  7. Golang服务可观测和思路分享

    省流 中医四诊"望闻问切"与程序诊断有异曲同工之妙.在Golang问题排查中,我们需要建立系统化的诊断思维:通过观察表象(望).收集信息(闻).追溯根源(问).精准施治(切)四个维 ...

  8. MySQL 中 `LIMIT 100000000, 10` 和 `LIMIT 10` 的执行速度是否相同?

    在MySQL中,LIMIT 100000000, 10和LIMIT 10的执行速度通常不会相同.它们的差异在于如何处理数据的检索. LIMIT 10: LIMIT 10表示从查询结果中获取前10条记录 ...

  9. uniapp阻止Modal模态框关闭

    要阻止uniapp的Modal模态框关闭,没有找到相关api,但可以通过保存配置立即打开的方式变相实现阻止关闭: const option = { title: "输入礼品券名称" ...

  10. 前端速成之路——html、css

    项目一知识点 单表视图列表 标题标签 <h1>用户注册</h1> 分割线与换行 <hr> <br> 表单提交 get:通过浏览器地址栏传递值 post: ...