BOJ 487 xor

时间限制 5000 ms  内存限制 65536 KB

题目描述

Given a sequence  A1,A2,,AN , you're required to answer the following queries: given three integers  l,r  and  x , find out  max{aix} , where  lir , and  ab  indicates the bitwise XOR(xor) operation.

输入格式

An integer  T(T10)  will exist in the first line of input, indicating the number of test cases. Each test case begins with two integers  N and  M(1N,M50000) , which separately denotes the length of the sequence and the number of queries. The following line gives  N  integers from  A1  to  AN . The next  M  lines, each with three integers  l,r,x(1lrN) , describe all the queries. All the elements in sequence  A  and the queried  x  will be set in range  [0,10000] .

输出格式

Output the answer for each query, one per line.

输入样例

1
3 2
1 3 2
1 2 1
1 3 1

输出样例

2
3
题意:

给你一段长度为 N 的数列,再给你 M 个查询, 问在 L ~ R 区间内与 x 异或最大的值

解题思路:

首先,我们明确地知道求一段区间内异或值最大的用Trie树查询,就是以该位的非值作为最优解查询,如果没有最优解不存在,或者不满足条件,则选择次优解,即该位本身数值。

其次是区间查询,在这里采用离线查询的方式,将查询按照R的大小查询,能够保证每一次查询的都满足小于R区间。L区间则是在Trie的find中维护,Trie的val数组维护的每一个经过该点的最大角标,然后就按照最优解是否存在,最优解是否在L的右边查询。

因为个人写的是递归的find,所以需要注意最后一位的处理。(之前没有判断最后一位的最优性....但是跑随机数都是对的

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#define eps 1e-9
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1; char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------

const int MAXN=500010;

struct Node
{
    int l,r,x;
    int idx,ans;
}a[MAXN];

int num[MAXN],ans_flag=0;
int n,q;

struct Trie
{
	int ch[2*MAXN][2];
	int v[2*MAXN];
	int sz;
	Trie(){ sz=1; }
	int idx(int x){ return x%2; }

	void insert(int x,int po)
	{
		int u=0;
		for(int i=13;i>=0;i--)
		{
			int c=idx(x>>i);//cout<<(x>>i)<<endl;
			if(!ch[u][c])
			{
				v[sz]=po;
				ch[u][c]=sz++;
			}
			v[u]=po;
//            cout<<" "<<u<<" "<<sz<<" "<<v[u]<<endl;
			u=ch[u][c];
		}
		v[u]=po;
//		cout<<x<<endl;
	}

	int find(int x,int l,int po,int i)
	{
	    if(i==-1&&v[po]>=l)
            return v[po];
        int c=idx(x>>i);//cout<<po<<" "<<i<<" "<<c<<" "<<v[po]<<endl;system("pause");
        if(ch[po][!c])
        {
            if(v[ch[po][!c]]>=l)
                return find(x,l,ch[po][!c],i-1);
            else
                return find(x,l,ch[po][c],i-1);
        }
        return find(x,l,ch[po][c],i-1);
	}

	void clear()
	{
	    sz=1;memset(ch,0,sizeof(ch));memset(v,0,sizeof(v));
	}
};

Trie s;

bool cmp(Node a,Node b)
{
    return a.r<b.r;
}

bool cmp1(Node a,Node b)
{
    return a.idx<b.idx;
}

int main()
{
    int T;
//    freopen("data.txt","r",stdin);
    read(T);
    while(T--)
    {
        s.clear();
        read(n),read(q);
        for(int i=1;i<=n;i++)
            read(num[i]);
        for(int i=1;i<=q;i++)
        {
            read(a[i].l);read(a[i].r);read(a[i].x);
            a[i].idx=i;
        }
        sort(a+1,a+q+1,cmp);
        int nr=1;
        for(int i=1;i<=q;i++)
        {
            ans_flag=0;
            for(int j=nr;j<=a[i].r;j++)
                s.insert(num[j],j);
            nr=a[i].r+1;
            a[i].ans=a[i].x^num[s.find(a[i].x,a[i].l,0,13)];//cout<<"  "<<a[i].ans<<endl;
        }
        sort(a+1,a+q+1,cmp1);
        for(int i=1;i<=q;i++)
            printf("%d\n",a[i].ans);
    }
    return 0;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值