版权声明:博主是菜鸡,但转的时候还是说一声吧 https://blog.csdn.net/qq_37666409/article/details/83187391
树状数组思博题,然鹅漏了l > mid > r的情况……我是不是该补脑了
#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;
const int MAXN = 100100;
const int LIM = 100000;
const int INF = 0x3f3f3f3f;
template<typename T> inline void CheckMax(T &A, T B) {
A < B ? A = B : A;
}
template<typename T> inline void CheckMin(T &A, T B) {
A > B ? A = B : A;
}
template <typename T> inline void read(T &x) {
int c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
#define lowbit(x) (x & -x)
int bit[MAXN], n, a[MAXN];
void update(int x, int y) {
for( ; x <= LIM; x += lowbit(x)) bit[x] += y;
}
int query(int x) {
int ret = 0;
for( ; x; x -= lowbit(x)) ret += bit[x];
return ret;
}
int L[MAXN], R[MAXN], L2[MAXN], R2[MAXN];
void solve() {
read(n);
memset(bit, 0, sizeof(bit));
for(int i = 1; i <= n; i++) {
read(a[i]);
L[i] = query(a[i] - 1);
L2[i] = i - 1 - L[i];
update(a[i], 1);
}
memset(bit, 0, sizeof(bit));
for(int i = n; i; i--) {
R[i] = query(LIM) - query(a[i]);
R2[i] = (n - i - R[i]);
update(a[i], 1);
}
long long ans = 0;
for(int i = 2; i < n; i++) ans += (long long) L[i] * (long long) R[i];
for(int i = 2; i < n; i++) ans += (long long) L2[i] * (long long) R2[i];
printf("%lld\n", ans);
}
int T;
signed main() {
read(T);
while(T--) {
solve();
}
return 0;
}
蜜汁RMQ,xjb维护一下同一个值的区间长度,特判l r是同一个值的情况和l r是相邻区间的情况
#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;
const int MAXN = 100100;
const int MAXE = 400400;
const int INF = 0x3f3f3f3f;
template<typename T> inline void CheckMax(T &A, T B) {
A < B ? A = B : A;
}
template<typename T> inline void CheckMin(T &A, T B) {
A > B ? A = B : A;
}
template <typename T> inline void read(T &x) {
int c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
int f[MAXN][19], a[MAXN], n, Q;
int belong[MAXN], l[MAXN], r[MAXN], cnt, len[MAXN];
void update() {
for(int i = 1; i <= cnt; i++) f[i][0] = len[i];
for(int j = 1; (1 << j) <= cnt; j++) {
for(int i = 1; i + (1 << j) - 1 <= cnt; i++) {
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
}
int query(int x, int y) {
int p = 0; while((1 << (p + 1)) <= (y - x + 1)) p++;
return max(f[x][p], f[y - (1 << p) + 1][p]);
}
signed main() {
read(n);
if(n == 0) return 0;
read(Q);
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1; i <= n; i++) {
if(a[i] != a[i - 1] || i == 1) {
r[cnt] = i - 1;
len[cnt] = r[cnt] - l[cnt] + 1;
l[++cnt] = i;
belong[i] = cnt;
continue;
}
belong[i] = cnt;
}
r[cnt] = n, len[cnt] = n - l[cnt] + 1;
update();
while(Q--) {
int x, y;
read(x), read(y);
if(belong[x] == belong[y]) {
printf("%d\n", y - x + 1);
continue;
}
int L = r[belong[x]] - x + 1;
int R = y - l[belong[y]] + 1;
x = belong[x] + 1;
y = belong[y] - 1;
if(x > y) {
printf("%d\n", max(L, R));
continue;
}
int ans = L;
CheckMax(ans, R);
CheckMax(ans, query(x, y));
printf("%d\n", ans);
}
main();
}
开双倍空间,将初始数组插入到MAXN + 1到MAXN + n,之后的操作按题意模拟,用树状数组维护前缀和即可
#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;
const int MAXN = 200200;
const int LIM = 100002;
const int INF = 0x3f3f3f3f;
template<typename T> inline void CheckMax(T &A, T B) {
A < B ? A = B : A;
}
template<typename T> inline void CheckMin(T &A, T B) {
A > B ? A = B : A;
}
template <typename T> inline void read(T &x) {
int c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
#define lowbit(x) (x & -x)
int bit[MAXN], n, a, Q, T, cnt = LIM - 1, pos[MAXN >> 1];
void update(int x, int y) {
for( ; x < MAXN; x += lowbit(x)) bit[x] += y;
}
int query(int x) {
int ret = 0;
for( ; x; x -= lowbit(x)) ret += bit[x];
return ret;
}
signed main() {
read(T);
while(T--) {
read(n); read(Q);
cnt = LIM - 1;
memset(bit, 0, sizeof(bit));
for(int i = 1; i <= n; i++) update(LIM + i, 1);
for(int i = 1; i <= n; i++) pos[i] = LIM + i;
for(int i = 1; i <= Q; i++) {
read(a);
printf("%d%c", query(pos[a] - 1), i == Q ? '\n' : ' ');
update(pos[a], -1);
pos[a] = cnt--;
update(pos[a], 1);
}
}
return 0;
}
线段树/树状数组板题,按题意模拟即可……最难的地方居然是输入
#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;
const int MAXN = 100100;
const int MAXE = 400400;
const int INF = 0x3f3f3f3f;
template<typename T> inline void CheckMax(T &A, T B) {
A < B ? A = B : A;
}
template<typename T> inline void CheckMin(T &A, T B) {
A > B ? A = B : A;
}
template <typename T> inline void read(T &x) {
int c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
struct SegmentTree {
int l, r, mn;
SegmentTree(int _l = 0, int _r = 0, int _mn = 0) : l(_l), r(_r), mn(_mn) {}
}tre[MAXE];
#define Ls(x) x << 1
#define Rs(x) x << 1 | 1
int n, Q, a[MAXN];
char s[35];
int opt[35], num[35];
void push_up(int x) {
tre[x].mn = min(tre[Ls(x)].mn, tre[Rs(x)].mn);
}
void build(int x, int l, int r) {
tre[x].l = l, tre[x].r = r;
if(l == r) {
tre[x].mn = a[l];
return ;
}
int mid = (l + r) >> 1;
build(Ls(x), l, mid);
build(Rs(x), mid + 1, r);
push_up(x);
}
void update(int x, int pos, int val) {
int l = tre[x].l, r = tre[x].r;
if(l == r) {
tre[x].mn = val;
return ;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(Ls(x), pos, val);
else update(Rs(x), pos, val);
push_up(x);
}
int query(int x, int L, int R) {
int l = tre[x].l, r = tre[x].r;
if(r < L || l > R) return INF;
if(L <= l && r <= R) return tre[x].mn;
int Min = INF;
CheckMin(Min, query(Ls(x), L, R));
CheckMin(Min, query(Rs(x), L, R));
return Min;
}
int get_number(char * str) {
int dex = 0;
int len = (int) strlen(str);
opt[dex] = 0;
bool flag = 0;
for(int i = 0; i < len; i++) {
if(isdigit(str[i])) {
opt[dex] = opt[dex] * 10 + str[i] - '0';
flag = 1;
}
else if(flag) opt[++dex] = 0;
}
return dex;
}
signed main() {
read(n), read(Q);
for(int i = 1; i <= n; i++) read(a[i]);
build(1, 1, n);
while(Q--) {
scanf("%s", s);
int len = get_number(s);
if(s[0] == 'q') {
printf("%d\n", query(1, opt[0], opt[1]));
}
else {
for(int i = 0; i < len; i++) num[i] = a[opt[i]];
for(int i = 0; i < len; i++) {
if(i + 1 < len) a[opt[i]] = num[i + 1];
else a[opt[i]] = num[0];
update(1, opt[i], a[opt[i]]);
}
}
}
return 0;
}