原文链接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. SQL Server 之 子查询与嵌套查询

    当由where子句指定的搜索条件指向另一张表时,就需要使用子查询或嵌套查询. 1 子查询 子查询是一个嵌套在select.insert.update或delete语句或其他子查询中的查询.任何允许使用 ...

  2. js对数组中的数字排序

    1 前言 如果数组里面都是数字,如果用原生的sort,默认是按字符串排序的,不符合我们的要求 2 代码 方法1:添加Array的原生方法 Array.prototype.sort2 =function ...

  3. 31)django-序列化

    目录 1)序列化 2)为什么不用json序列化 3)django序列化QuerySet,ErrorDict数据 一:序列化 序列化是将对象状态转换为可保持或传输的格式的过程 反序列化是指将存储在存储媒 ...

  4. 学习promise

    总概括 promise是js异步编程的一种解决方案 我对promise的认识(通俗):给一个承诺promise,如果未来发生的事情(异步操作)是符合满足相应条件,则接受resolve,否则失败reje ...

  5. Confluence 6 生产环境备份策略

    如果你是下面的情况,Confluence 的自动每日 XML 备份可能适合你: 正在评估使用 Confluence 你对数据库的管理并不是非常熟悉同时你的 Confluence 安装实例的数据量并不大 ...

  6. Confluence 6 数据库支持的驱动

    数据库 驱动已捆绑? JDBC 驱动 备注 更多信息 PostgreSQL 9.4-1202 JDBC 41 driver download 我们推荐你使用 JDBC 4 的驱动. 如果你希望使用更新 ...

  7. pytorch:修改预训练模型

    torchvision中提供了很多训练好的模型,这些模型是在1000类,224*224的imagenet中训练得到的,很多时候不适合我们自己的数据,可以根据需要进行修改. 1.类别不同 # codin ...

  8. windows与mac下安装nginx

    window下 下载链接,自己选一个版本下载 nginx官网下载 本人放在D盘: 启动nginx 有很多种方法启动nginx (1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过 (2)打开 ...

  9. GIL锁

    GIL锁                                                                           在CPython中,这个全局解释器锁,也称 ...

  10. 最长上升子序列(dp)

    链接:https://www.nowcoder.com/questionTerminal/d83721575bd4418eae76c916483493de来源:牛客网 广场上站着一支队伍,她们是来自全 ...