您的位置:首页 > 其它

HDU - 4417_Super Mario_主席树模板题

2017-11-11 19:42 465 查看

题意

区间【1, n】上,每个点都有一块处在某高度的石头。给 m 个询问,区间【l, r】上高度不大于 h 的石头有多少块。

思路

主席树模板题

链接

https://vjudge.net/contest/177348#problem/N

代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: