二分+RMQ/双端队列/尺取法 HDOJ 5289 Assignment
/*
题意:问有几个区间最大值-最小值 < 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的更多相关文章
- ACM-ICPC2018北京网络赛 80 Days(双端队列+尺取)
题目4 : 80 Days 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 80 Days is an interesting game based on Jules Ve ...
- POJ3662 SPFA//二分 + 双端队列最短路
https://cn.vjudge.net/problem/12427/origin 题意:求1到N第K + 1大条边权最小的路径 首先想到dp递推,dp[x][y]表示到x这个点经过y条免费边的最小 ...
- POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】
<题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...
- 双端队列(单调队列)poj2823 区间最小值(RMQ也可以)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 41844 Accepted: 12384 ...
- 双端队列 HDOJ 3530 Subsequence
题目传送门 题意:问最长子序列,满足区间最大值 - 最小值在[m, k]之间 分析:用双端队列维护最大值和最小值,保存的是位置.当满足条件时,更新最大值. /********************* ...
- 洛谷P3222 [HNOI2012]射箭(计算几何,半平面交,双端队列)
洛谷题目传送门 设抛物线方程为\(y=ax^2+bx(a<0,b>0)\),我们想要求出一组\(a,b\)使得它尽可能满足更多的要求.这个显然可以二分答案. 如何check当前的\(mid ...
- lintcode二叉树的锯齿形层次遍历 (双端队列)
题目链接: http://www.lintcode.com/zh-cn/problem/binary-tree-zigzag-level-order-traversal/ 二叉树的锯齿形层次遍历 给出 ...
- lintcode 滑动窗口的最大值(双端队列)
题目链接:http://www.lintcode.com/zh-cn/problem/sliding-window-maximum/# 滑动窗口的最大值 给出一个可能包含重复的整数数组,和一个大小为 ...
- STL---deque(双端队列)
Deque是一种优化了的.对序列两端元素进行添加和删除操作的基本序列容器.它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结 ...
随机推荐
- 常见问题:Linux安装Python3步骤、Windows无法利用pip
Linux安装python3.6和第三方库的步骤: 我的Linux是CentOS 6.5版本 Linux下大部分系统默认自带python2.x的版本,最常见的是python2.6或python2.7, ...
- Linux下汇编语言学习笔记27 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- Mycat集群方案收集(待实践)
先收集,后续再实践. 我想,市面上开源方案中,涉及到高可用和负载均衡的部署,无论是哪一个产品应用,都基本离不开LVS+Keepalived+HAProxy+Nginx等等. 下面是收集的教程: htt ...
- k-d树及八叉树
http://en.wikipedia.org/wiki/K-d_tree http://en.wikipedia.org/wiki/Octree
- GNS3配置SecureCRT
C:\SecureCRT\SecureCRT.exe /script D:\GNS3\DyRouter.vbs /T /telnet 127.0.0.1 %p "D:\Program Fil ...
- Java基础笔记(一)
本文主要是我在看<疯狂Java讲义>时的读书笔记,阅读的比较仓促,就用 markdown 写了个概要. 第一章 Java概述 Java SE:(Java Platform, Standar ...
- SpringMVC 学习笔记(五) 基于RESTful的CRUD
1.1. 概述 当提交的表单带有_method字段时,通过HiddenHttpMethodFilter 将 POST 请求转换成 DELETE.PUT请求,加上@PathVariable注解从而实现 ...
- SpringMVC学习指南-Spring框架
Spring框架主要使用依赖注入.实际上,很多牛叉的框架如Google的Guice都是使用依赖注入. ------------------------------------------------- ...
- 2016/1/21 练习 arraylist 1,添加 add() 2,遍历集合
package shuzu; public class Customer { //从源码中 使用字段生成构造函数 public Customer(String good, int price) { s ...
- 【HNOI模拟By lyp】Day2
1 toad1.1 题目描述 有 n 个石子, A B 两人博弈, A 先手. A 首先取若干个石子(至少一个,不能取完),然后B和A 再轮流取石子,每次取的石子不能超过 axb ( x 表示上次取的 ...