AtCoder Regular Contest 100 (ARC100) D - Equal Cut 二分
原文链接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 二分的更多相关文章
- AtCoder Regular Contest 100 (ARC100) E - Or Plus Max 其他
原文链接https://www.cnblogs.com/zhouzhendong/p/9251448.html 题目传送门 - ARC100E 题意 给定一个正整数 $n(n\leq 18)$. 然后 ...
- AtCoder Regular Contest 100 Equal Cut
Equal Cut 思路: 枚举中间那个分界点,然后两边找使得切割后差值最小的点,这个可以用双指针 代码: #include<bits/stdc++.h> using namespace ...
- AtCoder Regular Contest 100
传送门 C - Linear Approximation 题意: 求 \[ \sum_{i=1}^nabs(A_i-(b+i)) \] \(A_i,b\)给出. 思路: 将括号拆开,变为\(A_i-i ...
- 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 ...
- AtCoder Regular Contest 084 C - Snuke Festival【二分】
C - Snuke Festival ....最后想到了,可是不应该枚举a[],这样要二重循环,而应该枚举b[],这样只需一重循环... #include<iostream> #inclu ...
- AtCoder Beginner Contest 100 2018/06/16
A - Happy Birthday! Time limit : 2sec / Memory limit : 1000MB Score: 100 points Problem Statement E8 ...
- AtCoder Regular Contest 093
AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...
- AtCoder Regular Contest 102
AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...
- AtCoder Regular Contest 097
AtCoder Regular Contest 097 C - K-th Substring 题意: 求一个长度小于等于5000的字符串的第K小子串,相同子串算一个. K<=5. 分析: 一眼看 ...
随机推荐
- UVA 1395 MST
给你一个图, 求一个生成树, 边权Max – Min 要最小,输出最小值, 不能构成生成树的 输出 -1: 思路: Keuksal 算法, 先排序边, 然后枚举 第一条边, 往后加入边, 直到有 n- ...
- 前端 -----jQuery的位置信息
08-jQuery的位置信息 jQuery的位置信息跟JS的client系列.offset系列.scroll系列封装好的一些简便api. 一.宽度和高度 获取宽度 .width() 描述:为匹配的 ...
- 常见的SQL调优(SQL Tuning)Tips
建立适当的索引(参考<正确建立数据库索引的姿势>) 用UNION替换OR (适用于索引列) 用exist.not exist代替 in.not in 不要以字符格式声明数字(会 ...
- 【进阶1-4期】JavaScript深入之带你走进内存机制(转)
这是我在公众号(高级前端进阶)看到的文章,现在做笔记 https://mp.weixin.qq.com/s/yK4DPKhkmkiroasWJMrJcw 阅读笔记 JS内存空间分为栈(stack).堆 ...
- android高级页面效果集锦
程序员界有个神奇的网站,那就是github,这个网站集合了一大批优秀的开源框架,极大地节省了开发者开发的时间,在这里我进行了一下整理,这样可以使我们在使用到时快速的查找到,希望对大家有所帮助! 一个强 ...
- Java的动手动脑(七)
日期:2018.11.18 博客期:025 星期日 Part 1:使用 Files.walkFileTree()来找出指定文件夹下大小大于1KB的文件 package temp; import jav ...
- map函数和reduce函数的区别
①从参数方面来讲:map()函数: map()包含两个参数,第一个是参数是一个函数,第二个是序列(列表或元组).其中,函数(即map的第一个参数位置的函数)可以接收一个或多个参数.reduce()函数 ...
- django-admin的源码流程
一.admin的源码流程 首先可以确定的是:路由关系一定对应一个视图函数 a.当点击运行的时候,会先找到每一个app中的admin.py文件,并执行 b.执行urls.py admin.site是什么 ...
- mysql 各种关系代数的使用
连接(JOIN) 选择运算表示为: R⋈S ,其中R和S为不同的两个关系 连接运算是选取两个指定关系中的属性满足给定条件的元祖连接在一起来组成一个新的关系 数学形式: JOIN 关系名1 AND 关系 ...
- Winhex数据恢复笔记(五)
一.上次介绍了Windows API函数,这次对Windows API函数的参数做个笔记 1.IpFileName: 文件名指针,也可指向 MS-Dos设备名,同时支持文件和设备名,函数分为两个版本 ...