• [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;
    }
    
  • 相关阅读:
    圆周率的计算与进度条
    Python的使用方法
    Python科学计算库
    linux 命令总结[转]
    如何在 Windows 平台上下載 Android 的源码[转]
    装MSN报错问题解决 无法定位程序输入点except handler4 common 于动态链接库nsvcrt.dll【转】
    编写xorg.conf,简单三行解决ubuntu分辩率不可调的问题【转】
    谁说 Android 手机一定要 root 权限才能截屏?![转]
    给自己的忠告[转]
    lockdir加密bug[转]
  • 原文地址:https://www.cnblogs.com/dummyummy/p/10918210.html
Copyright © 2020-2023  润新知