[SCOI2016]美味——主席树+按位贪心

原题戳这里

题解

让异或值最大显然要按位贪心,然后我们还发现加上一个(x_i)的效果就是所有(a_i)整体向右偏移了,我们对于({a_i})开个主席树,支持查询一个区间中有多少个在([L,R])之间的数,查询时考虑一下(x_i)的影响就行了

#include <algorithm>
#include  <iostream>
#include   <cstdlib>
#include   <cstring>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <cmath>
#include     <ctime>
#include     <queue>
#include       <map>
#include       <set>

using namespace std;

#define ull unsigned long long
#define pii pair<int, int>
#define uint unsigned int
#define mii map<int, int>
#define lbd lower_bound
#define ubd upper_bound
#define INF 0x3f3f3f3f
#define IINF 0x3f3f3f3f3f3f3f3fLL
#define vi vector<int>
#define ll long long
#define mp make_pair
#define pb push_back
#define re register
#define il inline

#define N 200000
#define M 100000
#define A 300000
#define LIM 17

int n, m;
int a[N+5];
int nid, root[N+5], sumv[50*N+5], ch[2][50*N+5];

void insert(int o, int &u, int l, int r, int x) {
  u = ++nid;
  sumv[u] = sumv[o]+1;
  ch[0][u] = ch[0][o], ch[1][u] = ch[1][o];
  if(l == r) return ;
  int mid = (l+r)>>1;
  if(x <= mid) insert(ch[0][o], ch[0][u], l, mid, x);
  else insert(ch[1][o], ch[1][u], mid+1, r, x);
}

int query(int o, int u, int l, int r, int L, int R) {
  if(L <= l && r <= R) return sumv[u]-sumv[o];
  int mid = (l+r)>>1, ret = 0;
  if(L <= mid) ret += query(ch[0][o], ch[0][u], l, mid, L, R);
  if(R > mid) ret += query(ch[1][o], ch[1][u], mid+1, r, L, R);
  return ret;
}

int Query(int b, int x, int l, int r) {
  int ans = 0, t = 0;
  for(int bit = LIM; bit >= 0; --bit) {
    if((b>>bit)&1) {
      if(query(root[l-1], root[r], 0, A, max(0, t-x), max(0, t+(1<<bit)-1-x))) {
        ans |= (1<<bit);
      }
      else t |= (1<<bit);
    }
    else {
      if(query(root[l-1], root[r], 0, A, max(0, t+(1<<bit)-x), max(0, t+(1<<(bit+1))-1-x))) {
        t |= (1<<bit);
        ans |= (1<<bit);
      }
    }
  }
  return ans;
}

int main() {
  scanf("%d%d", &n, &m);
  for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), insert(root[i-1], root[i], 0, A, a[i]);
  for(int i = 1, b, x, l, r; i <= m; ++i) {
    scanf("%d%d%d%d", &b, &x, &l, &r);
    printf("%d
", Query(b, x, l, r));
  }
  return 0;
}
原文地址:https://www.cnblogs.com/dummyummy/p/10918210.html