bzoj3261: 最大异或和

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3261

题意:中文题。

分析:问题等价于求一个x与区间a[l]~a[r]之间的最大异或和。转为二进制树建可持久化字典树,在区间内跑最大值。O(nlogn)

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=300010;
const int MAX=100000000;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
char s[4];
int siz,e[30],a[2*N],root[2*N],tr[50*N][2],sum[50*N];
int add(int x,int z) {
    int i,y,t,ret=siz+1;
    siz++;y=siz;sum[y]=sum[x]+1;
    for (i=23;i>=0;i--) {
        t=(z&e[i])>>i;
        tr[y][0]=tr[x][0];tr[y][1]=tr[x][1];
        tr[y][t]=++siz;y=tr[y][t];
        x=tr[x][t];sum[y]=sum[x]+1;
    }
    return ret;
}
int query(int x,int y,int z) {
    int i,t,ret=0;
    for (i=23;i>=0;i--) {
        t=(z&e[i])>>i;
        if (sum[tr[y][t^1]]>sum[tr[x][t^1]]) {
            ret+=e[i];x=tr[x][t^1];y=tr[y][t^1];
        } else { x=tr[x][t];y=tr[y][t]; }
    }
    return ret;
}
int main()
{
    int i,n,m,l,r,x;
    e[0]=1;for (i=1;i<30;i++) e[i]=2*e[i-1];
    scanf("%d%d", &n, &m);
    n++;a[1]=0;
    for (i=2;i<=n;i++) scanf("%d", &a[i]);
    for (i=1;i<=n;i++) {
        a[i]^=a[i-1];root[i]=add(root[i-1],a[i]);
    }
    while (m--) {
        scanf("%s", s);
        if (s[0]=='A') {
            n++;scanf("%d", &a[n]);
            a[n]^=a[n-1];root[n]=add(root[n-1],a[n]);
        } else {
            scanf("%d%d%d", &l, &r, &x);
            printf("%d\n", query(root[l-1],root[r],x^a[n]));
        }
    }
    return 0;
}


你可能感兴趣的:(bzoj3261: 最大异或和)