题目传送门

 /*
题意:问有几个区间最大值-最小值 < k
解法1:枚举左端点,二分右端点,用RMQ(或树状数组)求区间最值,O(nlog(n))复杂度
解法2:用单调队列维护最值,O(n)复杂度,用法
解法3:尺取法,用mutiset维护最值
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std; typedef long long ll;
const int MAXN = 1e5 + ;
const int INF = 0x3f3f3f3f;
int a[MAXN];
int mn[MAXN][], mx[MAXN][]; //最多能保存524288的长度 int RMQ(int l, int r) {
int k = ; while (<<(k+) <= r - l + ) k++; //令k为满足1<<k <= r-l+1的最大整数
int MAX = max (mx[l][k], mx[r-(<<k)+][k]); //意思是区间最左边1<<k长度的最大值和最右边1<<k长度的最大值
int MIN = min (mn[l][k], mn[r-(<<k)+][k]); //可能有重叠的地方
return MAX - MIN;
} int main(void) { //HDOJ 5289 Assignment
freopen ("B.in", "r", stdin); int t; scanf ("%d", &t);
while (t--) {
int n, k; scanf ("%d%d", &n, &k);
for (int i=; i<=n; ++i) {
scanf ("%d", &a[i]);
mn[i][] = mx[i][] = a[i];
}
for (int j=; (<<j)<=n; ++j) {
for (int i=; i+(<<j)-<=n; ++i) {
mn[i][j] = min (mn[i][j-], mn[i+(<<(j-))][j-]); //mn[i][j]意思是从i开始,长度1<<j的区间的最小值
mx[i][j] = max (mx[i][j-], mx[i+(<<(j-))][j-]);
}
} ll ans = ;
for (int i=; i<=n; ++i) {
int l = i, r = n;
while (l + < r) { //二分使得l, r最远
int mid = (l + r) >> ;
if (RMQ (i, mid) < k) l = mid;
else r = mid;
}
if (RMQ (i, r) < k) { //此时[l, r](l+1==r) 其中一个一定满足条件
ans += (r - i + );
}
else {
ans += (l - i + );
}
}
printf ("%I64d\n", ans);
} return ;
}

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std; typedef long long ll;
const int MAXN = 1e5 + ;
const int INF = 0x3f3f3f3f;
int a[MAXN], n;
struct BIT {
int mn[MAXN], mx[MAXN]; void init(void) {
memset (mn, INF, sizeof (mn));
memset (mx, , sizeof (mx));
}
void add_min(int i, int x) {
while (i <= n) {
mn[i] = min (mn[i], x); i += i & (-i);
}
}
int query_min(int i) {
int res = INF;
while (i > ) {
res = min (res, mn[i]); i -= i & (-i);
}
return res;
}
void add_max(int i, int x) {
while (i <= n) {
mx[i] = max (mx[i], x); i += i & (-i);
}
}
int query_max(int i) {
int res = ;
while (i > ) {
res = max (res, mx[i]); i -= i & (-i);
}
return res;
}
}bit; int main(void) {
//freopen ("B.in", "r", stdin); int t; scanf ("%d", &t);
while (t--) {
int k; scanf ("%d%d", &n, &k);
for (int i=; i<=n; ++i) {
scanf ("%d", &a[i]);
} ll ans = ; bit.init ();
for (int i=n; i>=; --i) { //树状数组的特点,倒过来插入,求[i, n]区间
bit.add_min (i, a[i]);
bit.add_max (i, a[i]);
int l = i, r = n;
while (l <= r) {
int mid = (l + r) >> ;
int MAX = bit.query_max (mid);
int MIN = bit.query_min (mid);
if (MAX - MIN >= k) r = mid - ;
else l = mid + ;
}
ans += l - i;
}
printf ("%I64d\n", ans);
} return ;
}

树状数组

 /*
维护递增和递减的队列,当队首满足条件时,添加个数,再在从后添加元素,否则pop_front
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std; typedef long long ll;
const int MAXN = 1e5 + ;
const int INF = 0x3f3f3f3f;
struct Node {
int v, p;
};
int a[MAXN]; int main(void) {
//freopen ("B.in", "r", stdin); int t; scanf ("%d", &t);
while (t--) {
int n, k; scanf ("%d%d", &n, &k);
for (int i=; i<=n; ++i) scanf ("%d", &a[i]); deque<Node> Q1, Q2; ll ans = ; int head = ;
for (int i=; i<=n; ++i) {
Node now = (Node){a[i], i};
while (!Q1.empty ()) { //递减 队首max
Node tmp = Q1.back ();
if (now.v > tmp.v) Q1.pop_back ();
else break;
}
Q1.push_back (now);
while (!Q2.empty ()) { //递增 队首min
Node tmp = Q2.back ();
if (now.v < tmp.v) Q2.pop_back ();
else break;
}
Q2.push_back (now); if (i == ) ans++;
else {
while (true) {
Node big = Q1.front ();
Node small = Q2.front ();
if (big.v - small.v < k) break;
else {
if (small.p < big.p) {
head = small.p + ; Q2.pop_front ();
}
else {
head = big.p + ; Q1.pop_front ();
}
}
}
ans += i - head + ;
}
}
printf ("%I64d\n", ans);
} return ;
}

单调队列

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <cmath>
using namespace std; typedef long long ll;
const int MAXN = 1e5 + ;
const int INF = 0x3f3f3f3f;
multiset<int> S;
int a[MAXN]; int main(void) {
//freopen ("B.in", "r", stdin); int t; scanf ("%d", &t);
while (t--) {
int n, k; scanf ("%d%d", &n, &k);
for (int i=; i<=n; ++i) {
scanf ("%d", &a[i]);
} S.clear (); S.insert (a[]);
int l = , r = ; ll ans = ;
int mn, mx;
while (true) {
if (S.size ()) {
mn = *S.begin ();
mx = *S.rbegin ();
if (abs (a[r] - mn) < k && abs (a[r] - mx) < k) {
ans += S.size (); S.insert (a[r++]);
if (r > n) break;
}
else {
if (S.size ()) S.erase (S.find (a[l]));
l++;
}
}
else {
l = r; S.insert (a[r++]);
if (r > n) break;
}
} printf ("%I64d\n", ans + n);
} return ;
}

尺取法(multiset)

二分+RMQ/双端队列/尺取法 HDOJ 5289 Assignment的更多相关文章

  1. ACM-ICPC2018北京网络赛 80 Days(双端队列+尺取)

    题目4 : 80 Days 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 80 Days is an interesting game based on Jules Ve ...

  2. POJ3662 SPFA//二分 + 双端队列最短路

    https://cn.vjudge.net/problem/12427/origin 题意:求1到N第K + 1大条边权最小的路径 首先想到dp递推,dp[x][y]表示到x这个点经过y条免费边的最小 ...

  3. POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】

    <题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...

  4. 双端队列(单调队列)poj2823 区间最小值(RMQ也可以)

    Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 41844   Accepted: 12384 ...

  5. 双端队列 HDOJ 3530 Subsequence

    题目传送门 题意:问最长子序列,满足区间最大值 - 最小值在[m, k]之间 分析:用双端队列维护最大值和最小值,保存的是位置.当满足条件时,更新最大值. /********************* ...

  6. 洛谷P3222 [HNOI2012]射箭(计算几何,半平面交,双端队列)

    洛谷题目传送门 设抛物线方程为\(y=ax^2+bx(a<0,b>0)\),我们想要求出一组\(a,b\)使得它尽可能满足更多的要求.这个显然可以二分答案. 如何check当前的\(mid ...

  7. lintcode二叉树的锯齿形层次遍历 (双端队列)

    题目链接: http://www.lintcode.com/zh-cn/problem/binary-tree-zigzag-level-order-traversal/ 二叉树的锯齿形层次遍历 给出 ...

  8. lintcode 滑动窗口的最大值(双端队列)

    题目链接:http://www.lintcode.com/zh-cn/problem/sliding-window-maximum/# 滑动窗口的最大值 给出一个可能包含重复的整数数组,和一个大小为  ...

  9. STL---deque(双端队列)

    Deque是一种优化了的.对序列两端元素进行添加和删除操作的基本序列容器.它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结 ...

随机推荐

  1. 2018/4/7 Mybatis源码结构概览

    在观看Mybatis源码的过程中,有一点疑惑,就是Mybatis的缓存设计明显有问题,首先,Mybatis缓存分为两级,先说一级,生命周期为一个sqlsession,只有在查询相同方法时才会命中缓存, ...

  2. 【Intellij】Intellij Idea 2017创建web项目及tomcat部署实战

    相关软件:Intellij Idea2017.jdk16.tomcat7 Intellij Idea直接安装(可根据需要选择自己设置的安装目录),jdk使用1.6/1.7/1.8都可以,主要是配置好系 ...

  3. Thinkphp5.0 的使用模型Model添加数据

    Thinkphp5.0 的使用模型Model添加数据 使用create()方法添加数据 $res = TestUser::create([ 'name' => 'zhao liu', 'pass ...

  4. elasticsearch 安装ik中文分词

    https://blog.csdn.net/c5113620/article/details/79339541

  5. ZOJ 1298_Domino Effect

    题意: 多米诺骨牌效应:若干个关键牌相连,关键牌之间含有普通牌,关键牌倒下后其所在的行的普通牌全部倒下.求从推倒1号关键牌开始,最终倒下的牌的位置及时间. 分析: 最终倒下的牌的位置有两种情况,要么是 ...

  6. 洛谷——P1036 选数

    题目描述 已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n).从 n 个整数中任选 k 个整数相加,可分别得到一系列的和.例如当 n=4,k=3,4 个整数分别为 3,7,12, ...

  7. JSP的调试

    以下内容引用自http://wiki.jikexueyuan.com/project/jsp/debugging.html: 一.使用System.out.println() System.out.p ...

  8. 从epoll构建muduo-13 Reactor + ThreadPool 成型

    mini-muduo版本号传送门 version 0.00 从epoll构建muduo-1 mini-muduo介绍 version 0.01 从epoll构建muduo-2 最简单的epoll ve ...

  9. 修改windows下mysql的max_allowed_packet的值

    执行sql报错:Error updating database. Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is to ...

  10. 9种样式CSS3 渐变button集

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...