[多校2015.01.1002 单调队列] hdu 5289 Assignment
2015-07-26 14:45
363 查看
题意:
给你n个人和一个k
问你把这n个人分成多少个连续的子区间,要求区间每个数两两相差绝对值小于k
思路:
我们仅仅只需要对于当前位置,最左边那个和它绝对值相差大于等于k 的位置在哪
假设对于i这个位置,最左边的位置是tep,不存在的话tep=0
那么当且位置的贡献就是 sum[i]=min(i-max(x1,x2),sum[i-1]+1);
那么对于这个位置怎么求的话,我是使用了两个单调队列
同时维护两个单调队列
一个最大一个最小。
代码:
给你n个人和一个k
问你把这n个人分成多少个连续的子区间,要求区间每个数两两相差绝对值小于k
思路:
我们仅仅只需要对于当前位置,最左边那个和它绝对值相差大于等于k 的位置在哪
假设对于i这个位置,最左边的位置是tep,不存在的话tep=0
那么当且位置的贡献就是 sum[i]=min(i-max(x1,x2),sum[i-1]+1);
那么对于这个位置怎么求的话,我是使用了两个单调队列
同时维护两个单调队列
一个最大一个最小。
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"iostream" #include"map" using namespace std; #define N 222222 #define ll __int64 int q1 ,q2 ,v ; int main() { int t; cin>>t; while(t--) { int n,k; scanf("%d%d",&n,&k); for(int i=1; i<=n; i++) scanf("%d",&v[i]); int top1,top2,ed1,ed2,x1,x2; top1=top2=ed1=ed2=x1=x2=0; ll ans=0,sum=0; for(int i=1; i<=n; i++) { while(top1<ed1 && v[q1[ed1-1]]<=v[i] ) ed1--; //Max q1[ed1++]=i; while(top2<ed2 && v[q2[ed2-1]]>=v[i] ) ed2--; //Min q2[ed2++]=i; while(v[q1[top1]]-v[q2[top2]]>=k) { if(q1[top1]<q2[top2]) x1=q1[top1++]; else x2=q2[top2++]; } sum=min(sum+1,(ll)i-max(x1,x2)); ans+=sum; } printf("%I64d\n",ans); } return 0; }
相关文章推荐
- 使用apktool编译以及反编译apk文件
- 已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行,如何解决
- ios定位
- CF 558E(A Simple Task-计数排序+线段树)
- DT大数据梦工厂 第69讲
- C - A Simple Problem with Integers - poj 3468(区间更新)
- poj 3984 迷宫问题(广搜)
- Dijkstra — 最短路径算法
- ListView优化总结(二)--Android
- JAVA深入研究——Method的Invoke方法
- leetcode刷题。总结,记录,备忘 122
- DFS
- assert()函数用法总结
- 设计4个线程 其中两个线程每次对j增加1
- MYSQL---自定义函数
- [转载] 在Windows上将Apache Portable Runtime (APR)编译为DLL
- Nginx 笔记与总结(4)配置 server 访问日志
- [DT大数据梦工厂]-scala-helloworl的解析
- JS/Jquery的一些技巧
- windows 下常用端口