1 5 1 2 3 4 5 3 1 3 1 4 1 5
1 2 3
题意:
求某个区间内所有的连续递增三元组的个数,只要三元组中有一个数字不同就被认为是不同的三元组.
首先把数字离散化,然后对于某一个三元组,假设三个数分别是a,b,c,如果abc满足不严格的递增,
可以设这个三元组等于a*1e12+b*1e6+c,然后继续对三元组对应的数组离散化,然后只需要离线处理询问
的区间,拍完序之后用树状数组或者线段树统计区间只出现一次的数字的个数.
#include <bits/stdc++.h> using namespace std; #define maxn 211111 const long long num1 = 1e12; const long long num2 = 1e6; long long a[maxn]; int last [maxn], ans[maxn]; struct node { long long num; int pos; bool operator < (const node &a) const { return num < a.num; } }b[maxn]; int n, q; struct query { int l, r, id; bool operator < (const query &a) const { return l > a.l; } }qu[maxn]; int c[maxn]; int lowbit (int x) { return x&(-x); } void add (int pos, int num) { for (int i = pos; i <= n-2; i += lowbit (i)) { c[i] += num; } } int sum (int pos) { int ans = 0; for (int i = pos; i > 0; i -= lowbit(i)) { ans += c[i]; } return ans; } int main () { //freopen ("in.txt", "r", stdin); int t; scanf ("%d", &t); while (t--) { scanf ("%d", &n); for (int i = 1; i <= n; i++) { scanf ("%lld", &a[i]); b[i].pos = i, b[i].num = a[i]; } sort (b+1, b+1+n); scanf ("%d", &q); for (int i = 1; i <= q; i++) { scanf ("%d%d", &qu[i].l, &qu[i].r); qu[i].r -= 2; qu[i].id = i; } if (n == 1 || n == 2) { for (int i = 1; i <= q; i++) { printf ("0\n"); } continue; } int cnt = 0; for (int i = 1; i <= n; i++) { if (i > 1 && b[i].num == b[i-1].num) { a[b[i].pos] = cnt; } else a[b[i].pos] = ++cnt; } for (int i = 1; i <= n-2; i++) { if (a[i]<=a[i+1] && a[i+1]<=a[i+2]) b[i].num = a[i]*num1+a[i+1]*num2+a[i+2]; else b[i].num = 0; b[i].pos = i; } sort (b+1, b+1+n-2); cnt = 0; for (int i = 1; i <= n-2; i++) { if (b[i].num == 0) { a[b[i].pos] = 0; } else if (i > 1 && b[i].num == b[i-1].num) { a[b[i].pos] = cnt; } else a[b[i].pos] = ++cnt; } sort (qu+1, qu+1+q); memset (c, 0, sizeof c); memset (last, -1, sizeof last); for (int i = n-2; i >= qu[1].l; i--) { if (a[i] == 0) continue; if (last[a[i]] == -1) { last[a[i]] = i; add (i, 1); } else { add (last[a[i]], -1); add (i, 1); last[a[i]] = i; } } for (int i = 1; i <= q; i++) { if (i > 1 && qu[i].l < qu[i-1].l) { for (int j = qu[i-1].l-1; j >= qu[i].l; j--) { if (a[j] == 0) continue; else if (last[a[j]] == -1) { last[a[j]] = j; add (j, 1); } else { add (last[a[j]], -1); add (j, 1); last[a[j]] = j; } } } ans[qu[i].id] = sum (qu[i].r); } for (int i = 1; i <= q; i++) printf ("%d\n", ans[i]); } return 0; }