卧薪尝胆,厚积薄发。
SCOI2016 美味
Date: Wed Dec 12 21:13:26 CST 2018 In Category: NoCategory

Description:

给出 $n$ 个数 $a_i$ , $q$ 次询问,每次给出 $b,x,[l,r]$ ,询问 $[l,r]$ 中 $b_i\text{ xor }(a_i+x)$ 的最大值。
$1\leqslant n\leqslant 2\times 10^5,1\leqslant x,b,a\leqslant 10^5$

Solution:

显然建主席树然后按位贪心,注意每次在主席树上查询的区间。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n,m;
#define MAXN 200010
struct node
{
int lc,rc;
int sum;
node(){sum = 0;}
}t[MAXN * 19];
int ptr = 0;
int newnode(){return ++ptr;}
int root[MAXN];
#define mid ((l + r) >> 1)
#define N 100000
void build(int &rt,int l,int r)
{
rt = newnode();
if(l == r)return;
build(t[rt].lc,l,mid);
build(t[rt].rc,mid + 1,r);
return;
}
void insert(int &rt,int p,int l,int r)
{
int k = newnode();t[k] = t[rt];rt = k;
++t[k].sum;
if(l == r)return;
if(p <= mid)insert(t[rt].lc,p,l,mid);
else insert(t[rt].rc,p,mid + 1,r);
return;
}
int query(int rt,int L,int R,int l,int r)
{
if(L <= l && r <= R)return t[rt].sum;
int res = 0;
if(L <= mid)res += query(t[rt].lc,L,R,l,mid);
if(R > mid)res += query(t[rt].rc,L,R,mid + 1,r);
return res;
}
bool calc(int L,int R,int l,int r)
{
if(l > r)swap(l,r);
if(r < 0 || l > N)return false;
if(l < 0)l = 0;if(r > N)r = N;
return query(root[R],l,r,0,N) - query(root[L - 1],l,r,0,N);
}
int main()
{
scanf("%d%d",&n,&m);
build(root[0],0,N);
int x;
for(int i = 1;i <= n;++i)
{
scanf("%d",&x);
root[i] = root[i - 1];
insert(root[i],x,0,N);
}
int b,l,r;
for(int i = 1;i <= m;++i)
{
scanf("%d%d%d%d",&b,&x,&l,&r);
int ans = 0;
for(int k = 17;k >= 0;--k)
{
int L = ((ans + (1 << k)) ^ (b & (1 << k))) - x;
int R = ((ans + (1 << (k + 1)) - 1) ^ (b & (1 << k))) - x;
if(calc(l,r,L,R))ans += (1 << k);
ans ^= (b & (1 << k));
}
printf("%d\n",ans ^ b);
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡