HDU 5654 (樹狀陣列 離散化)
阿新 • • 發佈:2019-02-20
xiaoxin and his watermelon candy
Time Limit: 4000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 243 Accepted Submission(s): 64
Problem Description During his six grade summer vacation, xiaoxin got lots of watermelon candies from his leader when he did his internship at Tencent. Each watermelon candy has it's sweetness which denoted by an integer number.
xiaoxin is very smart since he was a child. He arrange these candies in a line and at each time before eating candies, he selects three continuous watermelon candies from a specific range [L, R] to eat and the chosen triplet must satisfies:
if he chooses a triplet (
1. j=i+1,k=j+1
2. ai≤aj≤ak
Your task is to calculate how many different ways xiaoxin can choose a triplet in range [L, R]?
two triplets (a0,a1,a2) and (b0,b1,b2) are thought as different if and only if:
a0≠b0 or a1≠b1 or a2≠b2
Input This problem has multi test cases. First line contains a single integer T
For each test case, the first line contains a single integer n(1≤n≤200,000)which represents number of watermelon candies and the following line contains ninteger numbers which are given in the order same with xiaoxin arranged them from left to right.
The third line is an integer Q
Output For each query, print an integer which represents the number of ways xiaoxin can choose a triplet.
Sample Input 1 5 1 2 3 4 5 3 1 3 1 4 1 5
Sample Output 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;
}