1. 程式人生 > >2017 ICPC 西安站現場賽 A.XOR (線段樹+線性基)(UVALive

2017 ICPC 西安站現場賽 A.XOR (線段樹+線性基)(UVALive

 XOR

Consider an array A with n elements. Each of its element is A[i] (1 ≤ i ≤ n). Then gives two integers
Q, K, and Q queries follow. Each query, give you L, R, you can get Z by the following rules.
 To get Z, at first you need to choose  some elements from A[L] to A[R], we call them A[i1], A[i2],
. . . , A[it], Then you can get number Z = K or (A[i1], A[i2], . . . , A[it]).
   Please calculate the maximum Z for each query .

Input
Several test cases.
First line an integer T (1 ≤ T ≤ 10). Indicates the number of test cases.
Then T  test cases follows. Each test case begins with three integer N, Q, K (1 ≤ N ≤ 10000,1 ≤
Q ≤ 100000, 0 ≤ K ≤ 100000). The next line has N integers indicate A[1] to A[N] (0 ≤ A[i] ≤ 108).
Then Q lines, each line two integer L, R (1 ≤ L ≤ R ≤ N).

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

Sample Input
1
5 3 0
1 2 3 4 5
1 3
2 4
3 5

Sample Output
3
7
7

題意:t組資料,然後輸入n,k,q,接著給出一個1個長度為n的陣列,q個詢問,對於每個詢問,詢問在下標為[l,r]的數中,選取一部分數,使得其異或值再OR上k後最大,輸出這個最大值。

思路:根據題意,選取一部分值得到異或最大值,可以想到線性基,但是最後要OR上k,所以要消除k對其影響,我們就把每個數轉化成二進位制,然後將k為1的位置對於每個數其位置就變為0,這樣就可以消除其k的影響了,最後在OR上k變回來,即為正確答案。比如數a[i]=6(110) ,k = 4(100),則a[i]應該變為(010)=2這樣來消除k的影響。由於多次區間詢問,所以用線段樹維護一下即可。

AC程式碼:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>

using namespace std;

#define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(a,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)

const double EXP = 1e-9;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const double DINF = 0xffffffffffff;
const int mod = 1e9+7;
const int N = 1e4+5;


//線性基
struct L_B{
    ll d[63],new_d[63];  //d陣列是第一次線性基,new_d是用於求Kth的線性基
    int cnt;             //記錄個數
    L_B(){
        memset(d,0,sizeof(d));
        memset(new_d,0,sizeof(new_d));
        cnt=0;
}
void clear(){
    memset(d,0,sizeof(d));
    memset(new_d,0,sizeof(new_d));
    cnt=0;
}
    bool ins(ll val){
        for(int i=62;i>=0;i--){
            if(val&(1ll<<i)){  //存在貢獻則繼續
                if(!d[i]){     //線性基不存在,選入線性基中
                    d[i]=val;
                    break;
                }
                val^=d[i];     //否則直接改變其值
            }
        }
        return val>0;          //大於0則是成功加入線性基的向量
    }
    ll query_max(){
        ll ans=0;
        for(int i=62;i>=0;i--)
            if((ans^d[i])>ans) //能讓值變大則選入
                ans^=d[i];
        return ans;
    }
    ll query_min(){
        for(int i=0;i<=62;i++)
            if(d[i])           //最小異或值
                return d[i];
        return 0;
    }
    //以下程式碼為求第k大異或值,其中cnt用於判斷是否可以取到0
    // cnt==n(數的個數)則不可以取到0,第k小就是第k小,否則第k小是第k-1小
    void rebuild()
    {
        for(int i=62;i>=0;i--)
            for(int j=i-1;j>=0;j--)
                if (d[i]&(1LL<<j))
                    d[i]^=d[j];
        for (int i=0;i<=62;i++)
            if (d[i])
                new_d[cnt++]=d[i];
    }
    ll kthquery(int k)
    {
        ll ans=0;
        if (k>=(1ll<<cnt))
            return -1;
        for (int i=62;i>=0;i--)
            if (k&(1ll<<i))
                ans^=new_d[i];
        return ans;
    }
};

//線性基合併,暴力合併
L_B merge(const L_B &n1,const L_B &n2)
{
    L_B ret=n1;
    for (int i=62;i>=0;i--)
        if (n2.d[i])
            ret.ins(n2.d[i]);
    return ret;
}

ll n,q,k,pd,a[N];
L_B A;

struct node{
    int lft,rht;
    L_B lb;
}tree[N<<2];

void pushUp(int id){
    tree[id].lb = merge(tree[id<<1].lb,tree[id<<1|1].lb);
}

void build(int id,int l,int r){
    tree[id].lft=l;
    tree[id].rht=r;
    if(l==r){
        tree[id].lb.clear();
        tree[id].lb.ins((a[l]&pd));
        return ;
    }
    int mid = (l+r)>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
    pushUp(id);
}

void query(int id,int l,int r){
    if(l==tree[id].lft&&r==tree[id].rht){
        A = merge(A,tree[id].lb);
        return ;
    }
    int mid = (tree[id].lft+tree[id].rht)>>1;
    if(r<=mid){
        query(id<<1,l,r);
    }
    else if(l>mid){
        query(id<<1|1,l,r);
    }
    else{
        query(id<<1,l,mid);
        query(id<<1|1,mid+1,r);
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld%lld",&n,&q,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        pd=0;
        for(int i=0;i<=62;i++){
            if(k&(1ll<<i))
                ;
            else
                pd+=(1ll<<i);
        }
        build(1,1,n);
        int l,r;
        while(q--){
            scanf("%d%d",&l,&r);
            A.clear();
            query(1,l,r);
            printf("%lld\n",A.query_max()|k);
        }
    }
    return 0;
}

相關推薦

2017 ICPC 西安現場 A.XOR 線段+線性

getchar tput 線性 calculate ext following case all pri XORConsider an array A with n elements. Each of its element is A[i] (1 ≤ i ≤ n). Th

2017 ICPC 西安現場 A.XOR 線段+線性UVALive

 XOR Consider an array A with n elements. Each of its element is A[i] (1 ≤ i ≤ n). Then gives two integers Q, K, and Q queries follow. Eac

2017 ACM-ICPC Asia Xi'an Problem A XOR異或線性

problem 線段樹 all gpo efi printf 異或 bre %d 題目鏈接 2017西安賽區 Problem A 題意 給定一個數列,和$q$個詢問,每個詢問中我們可以在區間$[L, R]$中選出一些數。    假設我們選出來的這個數列為$A[i_{

2017ICPC/ACM亞洲賽區西安現場 總結

2017.10.27早上9點半從學校出發去威海北,然後大概四小時到了濟南轉車,硬臥濟南到西安,時間剛剛好,大家也比較輕鬆,我們2個隊6個人剛好包了硬臥的一整個小包廂。晚上說說笑笑,談談學習、保研的事情,火車上沒什麼網,差不多十一點就睡了,第二天早上大概7點半,就到西安了。

2018 icpc徐州網路 H ——Ryuji doesn't want to study ——線段

題目連結:https://nanti.jisuanke.com/t/31460 題目思路:很明顯的一個線段樹題目,但是要求的是a[l]*len+a[l+1]*(len-1)+a[l+2]*(len-2)+......+a[r],所以根據這個推得以下公式: 可以試著推一下這個公式。所以我們維護

A Simple Problem with Integers線段區間更新

【題意】 給定長度為 NNN 的序列 AAA,有 QQQ次操作,操作分兩種 CabcC \ a \ b \ cCabc 表示將序列中 A[a,b]A[a,b]A[a,b]所有元素都加上一個數字 ccc QabQ \ a \ bQab 表示查詢序列 A[a,b]

ACM-ICPC 2018 徐州賽區網路預賽 H. Ryuji doesn't want to study線段區間求和

樣例輸入 5 3 1 2 3 4 5 1 1 3 2 5 0 1 4 5 樣例輸出 10 8 題意:n長的數列,q個詢問,1操作表示輸出l到r (r-l+1)*a[l]+(r-l)*a[l-1]+……+a[r]的和 ,2表示將a[l]更新為r 思路:線段樹

HDU 1698 Just a Hook線段-區間更新

In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sti

1698 Just a Hook 線段 區間更新

In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sti

HDU 1698 Just a Hook線段區間更新

題意: 屠夫是Dota中一個令所有英雄聞風喪膽的英雄。他有一個很長的鉤子,這個鉤子是用銅做的(剛剛開始都是1),現在他想要更改這些鉤子,把某個區間的鉤子改為金、銀或銅。 輸入 L, R,

hdu 1698 Just a Hook線段——區間更新

Just a Hook Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes

hdu1698 Just a Hook線段區間修改

Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is

hdu1698 Just a Hook線段+區間染色

#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt

POJ 1698 Just a Hook線段 區間更新

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 41166    Accepted Su

hdu1698——Just a Hook線段+區間更新

Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is

2014ACM/ICPC亞洲區域牡丹江現場-I ZOJ 3827 Information Entropy

esp osi mos wid integer blank border amount 什麽 Information Entropy Time Limit: 2 Seconds Memory Limit: 65536 KB Specia

2017 ACM-ICPC 西安網絡 F.Trig Function Chebyshev多項式

mod inf 技術 自己 def size pla names https 自己太菜,數學基礎太差,這場比賽做的很糟糕。本來想吐槽出題人怎麽都出很數學的題,現在回過頭來想還是因為自己太垃圾,競賽就是要多了解點東西。 找$f(cos(x))=cos(nx)$中$x^m$的

2017icpc西安網絡 Maximum Flow 找規律+數位dp

ron 結果 anti 成了 flow http cpc 求和 找規律 題目   https://nanti.jisuanke.com/t/17118 題意   有n個點0,1,2...n-1,對於一個點對(i,j)滿足i<j,那麽連一條邊,邊權為i xor j

ACM-ICPC 2017 沈陽賽區現場 G. Infinite Fraction Path && HDU 6223

沈陽 end cto fde div pid tails nod tps 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6223 參考題解:https://blog.csdn.net/qq_40482495/article/d

2016 ACM/ICPC亞洲區青島現場部分題解

多少 條件 技術 留下 tin tdi scanf .get max 摘要   本文主要列舉並求解了2016 ACM/ICPC亞洲區青島站現場賽的部分真題,著重介紹了各個題目的解題思路,結合詳細的AC代碼,意在熟悉青島賽區的出題策略,以備戰2018青島站現場賽。 HD