题目传送门

题意:现在有n个人,现在可以把这n个人分成若干组,只有连续的人才能被分为一组,并且一个组内最多2个人,现在问你 所有组内的最大值-最小值 这个差值最小是多少。

题解:

将每个人的情况3种情况都拿出来,把这些所有的情况从小到大排序,然后我们枚举起点,然后一直不停的添加线段,然后直到当前的区间内的所有线段,我们可以选择其中的一部分,使得这些线段能够不重合的前提下巧好覆盖1-n的区间内。

tree[x] 假设管理的区间为 [l, r]  tree[x][i][j] i代表的是左端点 j 代表的是右端点, 当i == 1 的时候,j == 1的时候,我们管理的是 [l+1,r+1]这个区间的状态 i == 0,j == 0 管理的是 [l, r]这个区间的状态。

所以我们pushup的时候不重合的搞就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 1e5 + ;
int a[N][];
pll p[N<<];
bool cmp(pll & x, pll & y){
return a[x.fi][x.se] < a[y.fi][y.se];
}
int tree[N<<][][];
void Build(int l, int r, int rt){
tree[rt][][] = tree[rt][][] = tree[rt][][] = tree[rt][][] = ;
if(l == r) {
tree[rt][][] = ;
return ;
}
int m = l+r >> ;
Build(lson); Build(rson);
}
void PushUp(int rt){
tree[rt][][] = (tree[rt<<][][] && tree[rt<<|][][]) || (tree[rt<<][][] && tree[rt<<|][][]);
tree[rt][][] = (tree[rt<<][][] && tree[rt<<|][][]) || (tree[rt<<][][] && tree[rt<<|][][]);
tree[rt][][] = (tree[rt<<][][] && tree[rt<<|][][]) || (tree[rt<<][][] && tree[rt<<|][][]);
tree[rt][][] = (tree[rt<<][][] && tree[rt<<|][][]) || (tree[rt<<][][] && tree[rt<<|][][]);
}
void Update(int L, int op,int l, int r, int rt){
if(l == r){
tree[rt][][op] ^= ;
return ;
}
int m = l+r >> ;
if(L <= m) Update(L, op, lson);
else Update(L, op, rson);
PushUp(rt);
}
int main(){
int T, n;
scanf("%d", &T);
while(T--){
scanf("%d", &n);
int m = ;
for(int i = ; i <= n; ++i){
scanf("%d", &a[i][]);
p[++m] = pll(i,);
if(i-) {
a[i-][] = a[i-][] + a[i][];
p[++m] = pll(i-,);
}
}
sort(p+, p++m, cmp);
Build(,n,);
LL ans = INF;
for(int i = , j=; i <= m; ++i){
while(j <= m && !tree[][][]){
Update(p[j].fi, p[j].se, , n, );
j++;
}
if(tree[][][]) ans = min(ans, 1ll*a[p[j-].fi][p[j-].se] - a[p[i].fi][p[i].se]);
Update(p[i].fi, p[i].se, , n, );
}
printf("%lld\n", ans);
}
return ;
}

最新文章

  1. pdf2htmlEx安装及测试
  2. 分享我的“艺术品”:公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享
  3. BZOJ 3524: [Poi2014]Couriers
  4. [转]Spring——jar包详解
  5. keepalived+haproxy构建高可用负载均衡
  6. [drp 4] 使用dom4j,读取XML数据,保存至数据库
  7. Linux重定向的理解
  8. JavaScript备忘录-原型
  9. javascript笔记05:函数表达式和函数语句的区别
  10. 微信开发第3章 通过accesstoken获取用户分组
  11. Codeforces Round #529 (Div. 3) C. Powers Of Two(数学????)
  12. 深入path类
  13. J2CACHE 两级缓存框架
  14. MT【57】2017联赛一试解答倒数第二题:一道不等式的最值
  15. Reflux系列01:异步操作经验小结
  16. Yii2框架bootstrap样式理解
  17. 【Android】事件处理系统
  18. 基于jQuery滑动分步式进度导航条代码
  19. (转)不要自称是程序员,我十多年的 IT 职场总结
  20. JavaScript中的数据结构及实战系列

热门文章

  1. 如何在github开源自己的项目
  2. ZK安装、ZK配置、ZK集群部署
  3. LongAdder和AtomicLong性能对比
  4. Echarts图表插件(4.x版本)使用(二、带分类筛选的多个图表/实例化多个ECharts,以关系图/force为例)
  5. Java | Map排序,工具类改进
  6. python_0基础开始_day05
  7. js 双向绑定数据
  8. apicloud 开发环境搭建
  9. p2p 打洞专场(转)
  10. 8.9 day30 并发编程 进程理论 进程方法 守护进程 互斥锁