题目描述
统计statistic
【问题描述】
给定N个数,有M个询问。每次询问一段区间内有没有出现过Xi这个数。
【输入格式】
第一行一个整数N。
第二行N个正整数表示给定的N个数。
第三行一个整数M。
以下M行每行三个整数li,ri和Xi;表示询问区间是[li, ri],询问数字是Xi。
【输出格式】
对于每一次询问,输出一个字符。0表示没出现,1表示出现了。
【样例输入输出】
statistic.in
statistic.out
5
1234567 666666 3141593 666666 4343434
5
1 5 3141593
1 5 578202
2 4 666666
4 4 7135610
1 1 1234567
10101
【数据说明】
40%的数据满足:N≤1000,M≤1000
100%的数据满足:N≤105,M≤105,Xi≤109
可以选择如下套餐:
套餐一:线段树+归并排序+二分查找
套餐二:主席树
套餐三:可持久化01trie
套餐四:分块
套餐五:莫队
(总之就是什么都可以水。。。)
(归并排序是个好东西。。。build的时候可以直接降一个log。。。不过查询的时候依旧是log2。。。)
(当然太蒻辣只会写线段树。。。)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const int N = 1e5 + 10;
vector<int> node[N * 4];
int n, m;
void build(int id, int l, int r) {
int m = (l + r) >> 1;
if(l == r) {
int val;
scanf("%d", &val);
node[id].push_back(val);
return;
}
build(id << 1, l, m);
build(id << 1 | 1, m + 1, r);
vector<int> &v1 = node[id << 1];
vector<int> &v2 = node[id << 1 | 1];
vector<int> &v = node[id];
for(int p1 = 0, p2 = 0, i = 1 ; i <= v1.size() + v2.size() ; i ++) {
if(p1 == v1.size()) {
v.push_back(v2[p2 ++]);
} else if(p2 == v2.size()) {
v.push_back(v1[p1 ++]);
} else {
if(v1[p1] < v2[p2]) {
v.push_back(v1[p1 ++]);
} else {
v.push_back(v2[p2 ++]);
}
}
}
}
int ask(int id, int x, int l, int r, int L, int R) {
int M = (L + R) >> 1;
if(L > r || R < l) return 0;
if(l <= L && R <= r) return *lower_bound(node[id].begin(), node[id].end(), x) == x;
return ask(id << 1, x, l, r, L, M) || ask(id << 1 | 1, x, l, r, M + 1, R);
}
int main() {
scanf("%d", &n);
build(1, 1, n);
scanf("%d", &m);
for(int i = 1, l, r, x ; i <= m ; i ++) {
scanf("%d%d%d", &l, &r, &x);
printf("%d", ask(1, x, l, r, 1, n));
}
}