1. 程式人生 > >4417_Super Mario_主席樹模板題

4417_Super Mario_主席樹模板題

題意

區間【1, n】上,每個點都有一塊處在某高度的石頭。給 m 個詢問,區間【l, r】上高度不大於 h 的石頭有多少塊。

思路

主席樹模板題

連結

程式碼

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn = 1e5 + 10;

int t, n, m;
int A[maxn];
int node[maxn << 3];
int rot[maxn], lson[maxn << 3
], rson[maxn << 3], num[maxn << 3], tt; int dct[maxn<<1], len; int a[maxn], b[maxn], h[maxn]; void ins(int l, int r, int pre, int& now, int x) { now = ++tt; if(l == r){ num[now] = num[pre] + 1; return; } lson[now] = lson[pre], rson[now] = rson[pre]; int
mid = (l + r) >> 1; if(x <= mid) ins(l, mid, lson[pre], lson[now], x); else ins(mid+1, r, rson[pre], rson[now], x); num[now] = num[lson[now]] + num[rson[now]]; } int query(int l, int r, int a, int b, int x, int y) { if(x > y) return 0; if(x <= l && r <= y) return
num[b] - num[a]; int mid = (l + r) >> 1; int res = 0; if(x <= mid) res += query(l, mid, lson[a], lson[b], x, y); if(y > mid) res += query(mid+1, r, rson[a], rson[b], x, y); return res; } int main() { //freopen("in.txt", "r", stdin); scanf("%d", &t); int cas = 0; while(t--) { printf("Case %d:\n", ++cas); tt = 0; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", A + i); dct[i] = A[i]; } for(int i = 1; i <= m; i++) { scanf("%d %d %d", a+i, b+i, h+i); dct[n+i] = h[i]; a[i]++, b[i]++; } sort(dct + 1, dct + 1 + n + m); len = unique(dct + 1, dct + n + m + 1) - dct - 1; for(int i = 1; i <= n; i++) { int d = lower_bound(dct + 1, dct + len + 1, A[i]) - dct; ins(1, len, rot[i-1], rot[i], d); } for(int i = 1; i <= m; i++) { int d = lower_bound(dct + 1, dct + len + 1, h[i]) - dct; printf("%d\n", query(1, len, rot[a[i]-1], rot[b[i]], 1, d)); } } return 0; }