日常训练 20170605 EasyProblem

来源:互联网 发布:淘宝工作人员的名片 编辑:程序博客网 时间:2024/05/20 01:46

给你 n 个正整数 ai,回答 m 个询问:
有三种询问:
XOR x,查询 max(ai xor x)
OR x,查询 max(ai or x)
AND x,查询 max(ai and x)
n,m100000 ,max(ai)<216
对于 xor 只要高位到低位依次满足尽量满足即可,相当与在 Trie 树上走。对与 andor 有些位是填 01 都一样,有些位是要尽量填某数的,然后我们就相当于把已经确定的位遮起来,然后枚举子集,这样复杂度满的话是 O(n×log(n)+m×max(ai)) 过不了的,但是今天是 IOI 赛制,我就交了一发,结果比他们写标算的都快了好几倍。其实如果对每个数预处理只要 O(n×log(n)+316)

#include<bits/stdc++.h>const int A = 1 << 16;template <typename T> void read(T &x) {    x = 0; char c = getchar();    for (; !isdigit(c); c = getchar());    for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';}int n, q, x, sum[A];bool exs[A], up[A];char op[5];int calc(int l, int r) {    if (!l) return sum[r];    return sum[r] - sum[l - 1];}int Xor(int x) {    int l = 0, r = A - 1, ans = 0;    for (int i=A>>1; l < r; i >>= 1) {        int mid = (l + r) >> 1;        if (x & i) {            if (calc(l, mid))                r = mid,                ans += i;            else                l = mid + 1;        }else {            if (calc(mid + 1, r))                l = mid + 1,                ans += i;            else                r = mid;        }    }    return ans;}int And(int x) {    for (int i=x; i>=0; i = (i - 1) & x)        if (up[i]) return i;}int Or(int x) {    int y = (A - 1) ^ x;    for (int i=y; i>=0; i = (i - 1) & y)        if (up[i]) return i | x;}int main() {    read(n); read(q);    while (n--)        read(x),        exs[x] = 1,        sum[x] = 1;    for (int i=1; i < A; i++)        sum[i] += sum[i - 1];    for (int i=0; i < A; i++)        if (exs[i])            for (int j=i; j>=0; j = (j - 1) & i) {                up[j] = 1;                if (!j) break;            }    while (q--) {        scanf("%s", op);read(x);        if (op[0] == 'X') printf("%d\n", Xor(x));        if (op[0] == 'A') printf("%d\n", And(x));        if (op[0] == 'O') printf("%d\n", Or(x));    }    return 0;}
原创粉丝点击