二分+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 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结 ...
随机推荐
- POJ 2778 (AC自动机+矩阵乘法)
POJ 2778 DNA Sequence Problem : 给m个只含有(A,G,C,T)的模式串(m <= 10, len <=10), 询问所有长度为n的只含有(A,G,C,T)的 ...
- 289. Game of Live
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...
- [bzoj2882]工艺_后缀数组
工艺 bzoj-2882 题目大意:题目链接. 注释:略. 想法: 跟bzoj1031差不多啊. 把串倍长后扫$sa$数组. 最后再统计答案即可. Code: #include <iostrea ...
- [TypeScript] Overload a Function with TypeScript’s Overload Signatures
Some functions may have different return types depending on the types of the arguments with which th ...
- easyui中点击datagrid的分页刷新按钮,数据无法更新到最新状态
原因分析:点击刷新按钮是对当前页数据进行reload,因此所传的请求参数皆为上一次加载当前页的参数即datagrid的load方法中的参数,主要是因为请求的最终时间无法更新到最新状态 解决方案:对点击 ...
- js 返回顶部
<script> window.onload = function(){ var oTop = document.getElementById("to_top"); v ...
- 通过uri呼起本地app
1.在Android本地app清单文件里配置 <activity android:name="com.mdj.ui.WelcomeActivity" android:scre ...
- JavaScript图片裁剪
1.jquery 图片裁剪库选择 Jcrop:http://deepliquid.com/content/Jcrop.html imgareaselect:http://odyniec.net/pro ...
- (二)Java 简介
Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式 ...
- input title 悬浮值
<!doctype html><html lang="en"> <head> <meta charset="UTF-8&quo ...