2017 ICPC西安区域赛 A - XOR (线段树并线性基)

链接:https://nanti.jisuanke.com/t/A1607

题面:

Consider an array AA with n elements . Each of its element is A[i]A[i] (1 \le i \le n)(1≤i≤n) . Then gives two integers QQ, KK, and QQ queries follow . Each query , give you LL, RR, you can get ZZ by the following rules.

To get ZZ , at first you need to choose some elements from A[L]A[L] to A[R]A[R] ,we call them A[i_1],A[i_2]…A[i_t]A[i1?],A[i2?]…A[it?] , Then you can get number Z = KZ=K or (A[i_1]A[i1?] xor A[i_2]A[i2?] … xor A[i_t]A[it?]) .

Please calculate the maximum ZZ for each query .

Input

Several test cases .

First line an integer TT (1 \le T \le 10)(1≤T≤10) . Indicates the number of test cases.Then TT test cases follows . Each test case begins with three integer NN, QQ, KK (1 \le N \le 10000,\ 1 \le Q \le 100000 , \ 0 \le K \le 100000)(1≤N≤10000, 1≤Q≤100000, 0≤K≤100000) . The next line has NN integers indicate A[1]A[1] to A[N]A[N] (0 \le A[i] \le 10^8)(0≤A[i]≤108). Then QQ lines , each line two integer LL, RR (1 \le L \le R \le N)(1≤L≤R≤N) .

Output

For each query , print the answer in a single line.

样例输入复制

1
5 3 0
1 2 3 4 5
1 3
2 4
3 5

样例输出复制

3
7
7

题目来源

ACM-ICPC 2017 Asia Xi‘an

跟树套树差不多,线段树每个节点建个线性基,写个合并函数,对k取反,每个数对取反后的k取且,就可以转化成线性基中取与k异或最大值了

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
const int M = 1e4+10;
int a[M];
struct L_B{
    int b[33],nb[33],tot;
    void init(){
        memset(b,0,sizeof(b));
    }

    bool Insert(int x){
        for(int i = 30;i >= 0;i --){
            if(x&(1<<i)){
                if(!b[i]){
                    b[i] = x;
                    break;
                }
                x ^= b[i];
            }
        }
        return x > 0;
    }

    int Max(int x){
        int ret = x;
        for(int i = 30;i >= 0;i --)
            ret = max(ret,ret^b[i]);
        return ret;
    }

    int Min(int x){
        int ret = x;
        for(int i = 0;i <= 30;i ++)
            if(b[i]) ret ^= b[i];
        return ret;
    }

    void rebuild(){
        for(int i = 30;i >= 0;i --)
            for(int j = i-1;j >= 0;j --)
                if(b[i]&(1<<j)) b[i]^=b[j];
        for(int i = 0;i <= 30;i ++)
            if(b[i]) nb[tot++] = b[i];
    }

    int K_Min(int k){
        int res = 0;
        if(k >= (1<<tot))
            return -1;
        for(int i = 30;i >= 0;i --)
            if(k&(1<<i))
                res ^= nb[i];
        return res;
    }

    L_B merge(L_B v){
        L_B ret;
        for(int i = 0;i <= 30;i ++) ret.b[i] = b[i];
        for(int i = 0;i <= 30;i ++){
            for(int j = i;j >= 0;j --){
                if(v.b[i]&(1<<j)){
                    if(ret.b[j]) v.b[i] ^= ret.b[j];
                    else {
                        ret.b[j] = v.b[i]; break;
                    }
                }
            }
        }
        return ret;
    }
}t[M<<2];

void build(int l,int r,int rt){
    if(l == r){
        t[rt].init();
        t[rt].Insert(a[l]);
        return ;
    }
    mid;
    build(lson); build(rson);
    t[rt] = t[rt<<1].merge(t[rt<<1|1]);
}

L_B query(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return t[rt];
    }
    mid;
    if(L <= m&&m < R) return query(L,R,lson).merge(query(L,R,rson));
    if(L <= m) return query(L,R,lson);
    if(R > m) return query(L,R,rson);
}

int main()
{
    int T,n,q,k,l,r;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&q,&k);
        k = ~k;
        for(int i = 1;i <= n;i ++)
            scanf("%d",&a[i]),a[i]&=k;
        k = ~k;
        build(1,n,1);
        for(int i = 1;i <= q;i ++){
            scanf("%d%d",&l,&r);
            L_B ans = query(l,r,1,n,1);
            int an = ans.Max(k);
            printf("%d\n",an);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/kls123/p/10849792.html

时间: 2024-10-09 01:39:03

2017 ICPC西安区域赛 A - XOR (线段树并线性基)的相关文章

【2017西安邀请赛:A】XOR(线段树+线性基)

前言:虽然已经有很多题解了,但是还是想按自己的理解写一篇. 思路:首先分析题目 一.区间操作 —— 线段树 二.异或操作 —— 线性基 这个两个不难想,关键是下一步的技巧 “或”运算 就是两个数的二进制中,对应位 只要有1,那么就是该位结果就是 1,所以要想k“或”运算后的结果尽量大, 就需要异或出的数,各个位上的1尽量多. 线性基的操作,可以求出区间最大异或和,但是我们需要的结果是  “或”运算. 所以我们可以将 k 取反,然后把所有数在加入线性基之前,全部 “与”运算一遍,再加入线性基. 这

【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个城市),保证任意两个城市都可以通过高速公路互达. 国正在筹划“八纵八横”的高铁建设计划,计划要修建一些高速铁路,每条高速铁路两端也都是城市(可能两端是同一个城市),也都有一个非负整数的经济影响因子.国家还计划在“八纵八横”计划建成之后,将“一带一路”扩展为“一带_路一

HAOI2017 八纵八横——线段树分治+线性基

题目大意 给定一个图,每次加一些边,或者删掉一些后来加上去的边,定义一个环的价值为环上所有的边的异或和,重复走的边重复算.每次询问这个时刻图中的所有经过1号点的环的最大价值. 思路 首先考虑对于一个静态的图如何求解图中所有经过1号点的环的最大价值,发现这个经过1号点就是唬人的,图中任意一个环都可以经过1号点再走回来. 于是题目变成了求解图中环的最大价值,可以将图中所有的简单环给拎出来放到线性基里面求最大价值,不难发现这是对的. 然后题目转化为了如何求图中所有的简单环,一般我们可以直接对图dfs找

Codeforces 938G 线段树分治 线性基 可撤销并查集

Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问x到y的路径异或最小值 保证图在任意时刻连通 首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来 有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用

2017 icpc 西安网络赛

F. Trig Function 样例输入 2 0 2 1 2 2 样例输出 998244352 0 2 找啊找啊找数列和论文.cosnx可以用切比雪夫多项式弄成(cosx)的多项式,然后去找到了相关的公式: 然后写个快速幂预处理啥的,很快就解决了~ 1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL lon

【2017 ICPC亚洲区域赛北京站 J】Pangu and Stones(区间dp)

In Chinese mythology, Pangu is the first living being and the creator of the sky and the earth. He woke up from an egg and split the egg into two parts: the sky and the earth. At the beginning, there was no mountain on the earth, only stones all over

线段树维护线性基并——17西安icpc a

#include<bits/stdc++.h> using namespace std; #define N 10005 int a[N],n,k,q; struct LB{ int b[35]; LB(){memset(b,0,sizeof b);} int check(int x){ for(int i=29;i>=0;i--)if(x>>i & 1){ if(!b[i])return 0; x^=b[i]; } return 1; } void insert(i

UVALive - 8512 线段树维护线性基(仅观赏)

题意:给定\(a[1...n]\),\(Q\)次询问求\(A[L...R]\)的异或组合再或上\(K\)的最大值 目前提交处于TLE状态,原因待查 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #include<ve

bzoj 4184: shallot (线段树维护线性基)

题面 \(solution:\) \(code:\) #include<iostream> #include<cstdio> #include<iomanip> #include<algorithm> #include<cstring> #include<cstdlib> #include<ctime> #include<cmath> #include<vector> #include<que