一个队列内部的元素具有单调性的一种数据结构,分为单调递增队列和单调递减队列。
令队列长度为 m m m
例如:有一个数列 2 , 5 , 4 , 5 , 3 , 4 , 6 , 8 , 5 {2,5,4,5,3,4,6,8,5} 2,5,4,5,3,4,6,8,5,以此构造一个 m = 3 m=3 m=3的单调递增队列
对于每个数实现过程
deque<int> q;
for (int i = 1; i <= n; i++) {
while (!q.empty() && a[q.back()] >= a[i])q.pop_back();
q.push_back(i);
while (!q.empty() && q.front() < i - m + 1)q.pop_front();
ans[i] = a[q.front()];
}
int l = 1, r = 0, q[1010];
for (int i = 1; i <= n; i++) {
while (r >= l && a[q[r]] >= a[i])r--;
q[++r] = i;
while (r >= l && q[l] < i - m + 1)l++;
ans[i] = a[q[l]];
}
给出n个数
让你查询每一个长度为m的区间内,从第一个元素开始最大值变换了几次,最大值是谁
把他们与i异或求和.
#include
#include
#include
using namespace std;
#pragma warning (disable:4996)
const int maxn = 10000005;
typedef long long LL;
class QIO {
public:
char buf[1 << 21], * p1 = buf, * p2 = buf;
int getc() {
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
int read() {
int ret = 0, f = 0;
char ch = getc();
while (!isdigit(ch)) {
if (ch == '-')
f = 1;
ch = getc();
}
while (isdigit(ch)) {
ret = ret * 10 + ch - 48;
ch = getc();
}
return f ? -ret : ret;
}
}io;
int n, m, k, p, q, r, mod;
int a[maxn];
void Read() {
n = io.read();
m = io.read();
k = io.read();
p = io.read();
q = io.read();
r = io.read();
mod = io.read();
for (int i = 1; i <= k; i++)
a[i] = io.read();
while (++k <= n)
a[k] = (LL(p) * a[k - 1] + LL(q) * k + r) % mod;
}
int maxrating[maxn], Count[maxn];
int dq[maxn];
void Queue(){
int head = 1, tail = 0;
for (int i = n; i > n - m + 1; i--) {
while (tail >= head && a[dq[tail]] <= a[i])tail--;
dq[++tail] = i;
}
for (int i = n - m + 1; i >= 1; i--) {
while (tail >= head && a[dq[tail]] <= a[i])tail--;
dq[++tail] = i;
while (tail >= head && dq[head] > i + m - 1)head++;
maxrating[i] = a[dq[head]] ^ i;
Count[i] = (tail - head + 1) ^ i;
}
}
int main() {
int t; t = io.read();
while (t--) {
Read();
Queue();
LL Rating = 0, Counts = 0;
for (int i = 1; i <= n - m + 1; i++) {
Rating = Rating + maxrating[i];
Counts = Counts + Count[i];
}
printf("%lld %lld\n", Rating, Counts);
}
}
给出一个数组
找出最大区间的最大值与最小值的差值在区间 [ m , k ] [m,k] [m,k]以内
#include
#include
#include
#include
using namespace std;
const int maxn = 100005;
typedef long long LL;
int a[maxn], q[maxn], dq[maxn];
int main() {
int n, m, k;
while (~scanf("%d%d%d", &n, &m, &k)) {
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int l = 1, r = 0, dl = 1, dr = 0, p = 0, maxl = 0;
for (int i = 1; i <= n; i++) {
while (r >= l && a[q[r]] <= a[i])r--;
q[++r] = i;
while (dr >= dl && a[dq[dr]] >= a[i]) dr--;
dq[++dr] = i;
while (r >= l && dr >= dl && a[q[l]] - a[dq[dl]] > k) {
if (q[l] < dq[dl]) {
p = q[l];
l++;
} else {
p = dq[dl];
dl++;
}
}
if (a[q[l]] - a[dq[dl]] >= m) {
maxl = max(maxl, i - p);
}
}
printf("%d\n", maxl);
}
}