原文链接https://www.cnblogs.com/zhouzhendong/p/9251420.html

题目传送门 - ARC100D

题意

  给你一个长度为 $n$ 的数列,请切 $3$ 刀,形成 $4$ 个连续非空子序列,问这 $4$ 个非空子序列的各自的元素和 的极差为多少。

  $n\leq 2\times 10 ^5$

题解

  如果切一刀,那么问题就很简单,尽量选中间的就可以了。

  可以二分一下在 $O(\log n)$ 的复杂度内解决。

  于是本题可以先枚举一下中间那条线,然后对于两边转化成刚才的子问题。

  然而!

  关键是:我居然没有想到,大概是脑抽了吧。

  然而!

  我通过乱搞过掉了!!

  本题第一次让我感受到了乱搞的强大!!

  UPD:突然发现正解可以通过指针扫一遍实现 $O(n)$ 。

代码

  正解我没写过。这里放乱搞,仅供观看,别喷谢谢。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200005;
int n;
LL a[N],sum[N],v;
int x[5]={0};
LL calc(int i){
return sum[x[i]]-sum[x[i-1]];
}
LL llabs(LL x){
return x<0?-x:x;
}
bool cmp(int a,int b){
return calc(a)<calc(b);
}
bool cmp2(int a,int b){
return calc(a)>calc(b);
}
void move(int id,int d){
if (d==1){
if (x[id+1]-x[id]>1)
x[id]++;
}
else {
if (x[id]-x[id-1]>1)
x[id]--;
}
}
LL trys(){
LL ans=1e17;
int y[5];
for (int i=0;i<5;i++)
y[i]=x[i];
for (int i=1;i<=20;i++){
int id[5]={0,1,2,3,4};
sort(id+1,id+5,cmp);
ans=min(ans,llabs(calc(id[1])-calc(id[4])));
int r=rand()%6;
if (r==0){
LL val=calc(1);
if (val>v)
move(1,-1);
else
move(1,1);
}
if (r==1){
LL val=calc(4);
if (val>v)
move(3,1);
else
move(3,-1);
}
if (r>1){
r-=2;
int k=r&1?2:3;
r/=2;
LL val=calc(k);
if (r){
if (val>v)
move(k-1,1);
else
move(k-1,-1);
}
else {
if (val>v)
move(k,-1);
else
move(k,1);
}
}
}
for (int i=0;i<5;i++)
x[i]=y[i];
return ans;
}
LL solve(){
for (int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
v=sum[n]/4;
for (int i=1;i<=3;i++){
x[i]=x[i-1]+1;
while (x[i]<n+i-4&&sum[x[i]]-sum[x[i-1]]<=v)
x[i]++;
}
x[4]=n;
LL ans=1e17;
for (int xxxx=1;xxxx<=n*4;xxxx++){
ans=min(ans,trys());
int id[5]={0,1,2,3,4};
sort(id+1,id+5,cmp);
ans=min(ans,llabs(calc(id[1])-calc(id[4])));
int j=1;
while (j<=4&&(id[j]==1||x[id[j]-1]-x[id[j]-2]==1))
j++;
if (j>4)
break;
x[id[j]-1]--;
}
return ans;
}
LL solve2(){
for (int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
v=sum[n]/4;
for (int i=1;i<=3;i++){
x[i]=x[i-1]+1;
while (x[i]<n+i-4&&sum[x[i+1]]-sum[x[i]]<=v)
x[i]++;
}
x[4]=n;
LL ans=1e17;
for (int xxxx=1;xxxx<=n*4;xxxx++){
int id[5]={0,1,2,3,4};
sort(id+1,id+5,cmp2);
ans=min(ans,llabs(calc(id[1])-calc(id[4])));
int j=1;
while (j<=4&&(id[j]==1||x[id[j]-1]-x[id[j]-2]==1))
j++;
if (j>4)
break;
x[id[j]-1]--;
}
return ans;
}
int main(){
srand(19260817);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lld",&a[i]);
LL ans=1e17;
ans=min(ans,solve());
for (int i=1;i<=n/2;i++)
swap(a[i],a[n-i+1]);
ans=min(ans,solve());
ans=min(ans,solve2());
for (int i=1;i<=n/2;i++)
swap(a[i],a[n-i+1]);
ans=min(ans,solve2());
printf("%lld",ans);
return 0;
}

  

AtCoder Regular Contest 100 (ARC100) D - Equal Cut 二分的更多相关文章

  1. AtCoder Regular Contest 100 (ARC100) E - Or Plus Max 其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/9251448.html 题目传送门 - ARC100E 题意 给定一个正整数 $n(n\leq 18)$. 然后 ...

  2. AtCoder Regular Contest 100 Equal Cut

    Equal Cut 思路: 枚举中间那个分界点,然后两边找使得切割后差值最小的点,这个可以用双指针 代码: #include<bits/stdc++.h> using namespace ...

  3. AtCoder Regular Contest 100

    传送门 C - Linear Approximation 题意: 求 \[ \sum_{i=1}^nabs(A_i-(b+i)) \] \(A_i,b\)给出. 思路: 将括号拆开,变为\(A_i-i ...

  4. AtCoder Regular Contest 100 E - Or Plus Max

    一道很好的dp题 dp[K]存的是 i满足二进制1属于K二进制1位置 最大的两个Ai 这样dp[K]统计的两个数肯定满足(i | j) <= K 然后不断做 update(dp[i | (1&l ...

  5. AtCoder Regular Contest 084 C - Snuke Festival【二分】

    C - Snuke Festival ....最后想到了,可是不应该枚举a[],这样要二重循环,而应该枚举b[],这样只需一重循环... #include<iostream> #inclu ...

  6. AtCoder Beginner Contest 100 2018/06/16

    A - Happy Birthday! Time limit : 2sec / Memory limit : 1000MB Score: 100 points Problem Statement E8 ...

  7. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  8. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

  9. AtCoder Regular Contest 097

    AtCoder Regular Contest 097 C - K-th Substring 题意: 求一个长度小于等于5000的字符串的第K小子串,相同子串算一个. K<=5. 分析: 一眼看 ...

随机推荐

  1. 转载:MySQL字段类型

    原文:https://www.cnblogs.com/jennyyin/p/7895010.html 数值类型 类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 字节 (-128, ...

  2. linux 提高代码质量的工具

    很多IT公司对于软件开发都有严格的分工,这包括设计.测试.服务支持等等.但是,我一直都认为只有开发者才是真正对软件质量负责的人.没有好的软件设计,软件质量基本上是无从谈起.当然,要做到这一点是需要额外 ...

  3. Linux/Ubuntu安装搜狗输入法

    零.你首先需要安装fcitx小企鹅输入法,相信绝大部分用linux的中国人都用这个输入法,安装fcitx后同时还能解决Sublime Text的中文输入问题. 安装fcitx输入法前首先要安装fcit ...

  4. python之__call__()

    __call__ 在Python中,函数其实是一个对象: >>> f = abs >>> f.__name__ 'abs' >>> f(-123) ...

  5. TCP和UDP的对比

    UDP #面向报文 UDP 是一个面向报文(报文可以理解为一段段的数据)的协议.意思就是 UDP 只是报文的搬运工,不会对报文进行任何拆分和拼接操作. 具体来说 在发送端,应用层将数据传递给传输层的 ...

  6. LeetCode(1): 两数之和

    本内容为LeetCode第一道题目:两数之和 # -*- coding: utf-8 -*- """ Created on Sun Mar 10 19:57:18 201 ...

  7. SSM 三大框架---事务处理

    SSM 三大框架---事务处理 原创 2016年05月12日 20:57:03 标签: spring / J2EE / java / 框架 / 事务 7010 在学习三大框架的时候,老师说事务处理是最 ...

  8. R2CNN项目部分代码学习

    首先放出大佬的项目地址:https://github.com/yangxue0827/R2CNN_FPN_Tensorflow 那么从输入的数据开始吧,输入的数据要求为tfrecord格式的数据集,好 ...

  9. Centos7搭建dhcp服务器

    实验拓扑: 实验步骤如下: 1.挂载本地镜像,并安装dhcp组件. 2.更改配置文件,并重启服务. . 3.配置dhcp地址池范围 4.配置防火墙 结果:在客户端上,重启网卡,后查看ip

  10. 滴水穿石-07Java开发中常见的错误

    1:使用工具Eclipse 1.1 "语法错误" 仅当源级别为 1.5 时已参数化的类型才可用 设置eclipse,窗口—>java—>编译器—>JDK一致性调到 ...