bzoj2844解题报告
2014年6月19日 20:33
题意
给出n个数,在这n个数中选任意多的数进行异或,共产生了2n个含重复数字的数,现给出一个数q,问若将q插入这2n个数中,q是第几小的
算法分析
先对着n个数进行高斯消元,得到m个非零数和n-m个0,那m个非零的值就可组成2n种数,每个重复2n-m次。只要按位统计q在其中排在第几位就可以了。
给出n个数,在这n个数中选任意多的数进行异或,共产生了2n个含重复数字的数,现给出一个数q,问若将q插入这2n个数中,q是第几小的
先对着n个数进行高斯消元,得到m个非零数和n-m个0,那m个非零的值就可组成2n种数,每个重复2n-m次。只要按位统计q在其中排在第几位就可以了。
给定一个数列,给出若干个询问(l,r,k),求出[l,r]区间内第k小的数。
用若干棵线段树分别维护前缀\(S_i\)的离散化后的该数的个数,即在某棵线段树中,第i个位置表示离散化后大小为i的元素的个数,查询时在线段树上进行二分。
#include <cstdio>
#include <cstring>
#include <cstdlib>
class node{
public:
int l,r, sum;
node *linkl, *linkr;
};
const int nn=100005;
node* root[nn];
class node1{
public:
int x, num;
} a1[nn];
int a[nn];
int num;
int hash[nn];
int n,m;
void build(node *&p, int l, int r){
p=(node*)malloc(sizeof(node));
p->l = l; p->r = r; p->linkl = p->linkr = NULL;
if (l < r){
int mid = (l + r) >> 1;
build(p->linkl, l, mid);
build(p->linkr, mid+1, r);
p->sum = p->linkl->sum + p->linkr->sum;
} else{
p->sum = 0;
}
}
void build1(int x, node *&p, node *p1, int l,int r){
p=(node*)malloc(sizeof(node));
p->l = l; p->r = r;
p->linkl = p->linkr = NULL;
if (l < r) {
int mid = (l + r) >> 1;
if (x <= mid){
build1(x, p->linkl, p1->linkl, l, mid);
p->linkr = p1->linkr;
} else {
build1(x, p->linkr, p1->linkr, mid+1, r);
p->linkl = p1->linkl;
}
p->sum = p->linkl->sum + p->linkr->sum;
} else p->sum = p1->sum + 1;
}
inline int check(node *p1, node *p2, int k){
while (p1->l != p1->r){
if (k <= p2->linkl->sum - p1->linkl->sum) {
p2 = p2 -> linkl; p1 = p1 -> linkl;
} else{
k -= (p2 -> linkl->sum - p1->linkl->sum);
p2 = p2 -> linkr; p1 = p1 ->linkr;
}
}
return (p1->l);
}
int scan(){
char c;
int x(0);
bool f(false);
while(c=getchar(),c==' ' || c== '\n');
if (c == '-') {
f = true;
c = getchar();
}
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';
if (f) x = 0 - x;
return x;
}
void qsort(int l, int r){
node1 mid=a1[(l + r) >> 1];
int i(l), j(r);
node1 t;
do{
while (a1[i].x < mid.x) ++i;
while (a1[j].x > mid.x) --j;
if (i <= j){
t = a1[i]; a1[i] = a1[j]; a1[j] = t;
++i; --j;
}
} while (i < j);
if (l < j) qsort(l, j);
if (i < r) qsort(i, r);
}
int main(){
freopen("poj2104.in", "r", stdin);
freopen("poj2104.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i=1;i<=n;++i){
a1[i].x = scan();
a1[i].num = i;
}
qsort(1, n);
a[a1[1].num] = 1;
hash[1] = a1[1].x;
num = 1;
for (int i=2;i<=n;++i){
if (a1[i].num != a1[i-1].num) ++num;
a[a1[i].num] = num;
hash[num] = a1[i].x;
}
build(root[0], 1, num);
for (int i=1;i<=num;++i) build1(a[i], root[i], root[i-1], 1, num);
int l,r,k;
for (int i=1;i<=m;++i){
l = scan(); r = scan(); k = scan();
printf("%d\n", hash[check(root[l-1], root[r], k)]);
}
fclose(stdin);
fclose(stdout);
return 0;
}