BZOJ 4103 [Thu Summer Camp 2015]异或运算 可持久化Trie
2016-01-01 17:59
531 查看
对矩阵求第k大xor值。
注意到数据范围长宽严重失调(误
所以对于每列维护可持久化Trie。
然后查询就由BZOJ 3261推广一下就好啦。
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 1001, M = 300001;
using namespace std;
struct Trie {
Trie* c[2]; int size;
Trie() { c[0] = c[1] = NULL; size = 0; }
Trie(Trie *l, Trie *r, int sz) { c[0] = l, c[1] = r, size = sz; }
void* operator new(size_t) {
static Trie pool[M * 60], *pointer = pool;
return pointer++;
}
static Trie* put(Trie *p, int x, int digit) {
if (!digit)
return new Trie(p->c[0], p->c[1], p->size + 1);
if (x & digit)
return new Trie(p->c[0], put(p->c[1], x, digit >> 1), p->size + 1);
else
return new Trie(put(p->c[0], x, digit >> 1), p->c[1], p->size + 1);
}
static int get(Trie *p1[], Trie *p2[], int *x, int len, int digit, int k) {
int i, sz = 0;
if (!digit)
return 0;
#define rson (bool(~x[i] & digit))
#define son (bool( x[i] & digit))
for (i = 1; i <= len; i++)
sz += p1[i]->c[rson]->size,
sz -= p2[i]->c[rson]->size;
if (k <= sz) {
for (i = 1; i <= len; i++)
p1[i] = p1[i]->c[rson],
p2[i] = p2[i]->c[rson];
return digit | get(p1, p2, x, len, digit >> 1, k);
} else {
for (i = 1; i <= len; i++)
p1[i] = p1[i]->c[ son],
p2[i] = p2[i]->c[ son];
return get(p1, p2, x, len, digit >> 1, k - sz);
}
}
};
int main() {
static int x
, y[M], a
;
static Trie *p1
, *p2
, *trie[M];
int i, dep = 1 << 30, n, m, q, l1, l2, r1, r2, k;
scanf("%d%d", &n, &m);
for (i = 1; i <= n; i++) scanf("%d", &x[i]);
for (i = 1; i <= m; i++) scanf("%d", &y[i]);
trie[0] = new Trie();
trie[0]->c[0] = trie[0]->c[1] = trie[0];
for (i = 1; i <= m; i++)
trie[i] = Trie::put(trie[i - 1], y[i], dep);
scanf("%d", &q);
while (q--) {
scanf("%d%d%d%d%d", &l1, &r1, &l2, &r2, &k);
int len = r1 - l1 + 1;
fill(p1 + 1, p1 + len + 1, trie[r2]);
fill(p2 + 1, p2 + len + 1, trie[l2 - 1]);
memcpy(a + 1, x + l1, sizeof(int) * len);
printf("%d\n", Trie::get(p1, p2, a, len, dep, k));
}
return 0;
}
Submit: 171 Solved: 96
[Submit][Status][Discuss]
第二行包含n个非负整数xi
第三行包含m个非负整数yj
第四行包含一个正整数p,表示询问次数
随后p行,每行均包含5个正整数,用来描述一次询问,每行包含五个正整数u,d,l,r,k,含义如题意所述。
1 2 4
7 6 5
3
1 2 1 2 2
1 2 1 3 4
2 3 2 3 4
5
1
1<=u<=d<=n<=1000,
1<=l<=r<=m<=300000,
1<=k<=(d-u+1)*(r-l+1),
1<=p<=500
注意到数据范围长宽严重失调(误
所以对于每列维护可持久化Trie。
然后查询就由BZOJ 3261推广一下就好啦。
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 1001, M = 300001;
using namespace std;
struct Trie {
Trie* c[2]; int size;
Trie() { c[0] = c[1] = NULL; size = 0; }
Trie(Trie *l, Trie *r, int sz) { c[0] = l, c[1] = r, size = sz; }
void* operator new(size_t) {
static Trie pool[M * 60], *pointer = pool;
return pointer++;
}
static Trie* put(Trie *p, int x, int digit) {
if (!digit)
return new Trie(p->c[0], p->c[1], p->size + 1);
if (x & digit)
return new Trie(p->c[0], put(p->c[1], x, digit >> 1), p->size + 1);
else
return new Trie(put(p->c[0], x, digit >> 1), p->c[1], p->size + 1);
}
static int get(Trie *p1[], Trie *p2[], int *x, int len, int digit, int k) {
int i, sz = 0;
if (!digit)
return 0;
#define rson (bool(~x[i] & digit))
#define son (bool( x[i] & digit))
for (i = 1; i <= len; i++)
sz += p1[i]->c[rson]->size,
sz -= p2[i]->c[rson]->size;
if (k <= sz) {
for (i = 1; i <= len; i++)
p1[i] = p1[i]->c[rson],
p2[i] = p2[i]->c[rson];
return digit | get(p1, p2, x, len, digit >> 1, k);
} else {
for (i = 1; i <= len; i++)
p1[i] = p1[i]->c[ son],
p2[i] = p2[i]->c[ son];
return get(p1, p2, x, len, digit >> 1, k - sz);
}
}
};
int main() {
static int x
, y[M], a
;
static Trie *p1
, *p2
, *trie[M];
int i, dep = 1 << 30, n, m, q, l1, l2, r1, r2, k;
scanf("%d%d", &n, &m);
for (i = 1; i <= n; i++) scanf("%d", &x[i]);
for (i = 1; i <= m; i++) scanf("%d", &y[i]);
trie[0] = new Trie();
trie[0]->c[0] = trie[0]->c[1] = trie[0];
for (i = 1; i <= m; i++)
trie[i] = Trie::put(trie[i - 1], y[i], dep);
scanf("%d", &q);
while (q--) {
scanf("%d%d%d%d%d", &l1, &r1, &l2, &r2, &k);
int len = r1 - l1 + 1;
fill(p1 + 1, p1 + len + 1, trie[r2]);
fill(p2 + 1, p2 + len + 1, trie[l2 - 1]);
memcpy(a + 1, x + l1, sizeof(int) * len);
printf("%d\n", Trie::get(p1, p2, a, len, dep, k));
}
return 0;
}
4103: [Thu Summer Camp 2015]异或运算
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 171 Solved: 96
[Submit][Status][Discuss]
Description
给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij。Input
第一行包含两个正整数n,m,分别表示两个数列的长度第二行包含n个非负整数xi
第三行包含m个非负整数yj
第四行包含一个正整数p,表示询问次数
随后p行,每行均包含5个正整数,用来描述一次询问,每行包含五个正整数u,d,l,r,k,含义如题意所述。
Output
共p行,每行包含一个非负整数,表示此次询问的答案。Sample Input
3 31 2 4
7 6 5
3
1 2 1 2 2
1 2 1 3 4
2 3 2 3 4
Sample Output
65
1
HINT
对于100%的数据,0<=Xi,Yj<2^31,1<=u<=d<=n<=1000,
1<=l<=r<=m<=300000,
1<=k<=(d-u+1)*(r-l+1),
1<=p<=500
相关文章推荐
- [nRF51822] 5、 霸屏了——详解nRF51 SDK中的GPIOTE(从GPIO电平变化到产生中断事件的流程详解)
- C++ 的名字查找(name lookup)
- lcp+dp Codeforces611D New Year and Ancient Prophecy
- android5.1中apn选项默认选择制式源码修改
- org.openqa.selenium.StaleElementReferenceException
- 前端学PHP之基础语法
- 启示录
- android5.1源码中加全局变量
- 语言相关
- POJ1064 Cable master(二分)
- 为什么说“医可救众生?佛可救众生!”
- screen的使用和小故障
- 《oranges:一个操作系统的实现》阅读笔记
- 理论: 图论(5): 无权图的最短路径
- JTS介绍
- 百度云网盘高速通道加速破解版 去广告纯净版干净云
- ubuntu12.04设置网桥
- java14.语言进阶------本地文件操作---文件属性的读取、设置
- 一道简单DP题
- forin用法