• 【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L


    Description

    FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和。
    即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。
    为了体现在线操作,对于一个询问(x,y):
    l = min ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
    r = max ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
    其中lastans是上次询问的答案,一开始为0。

    Input

    第一行两个整数N和M。
    第二行有N个正整数,其中第i个数为Ai,有多余空格。
    后M行每行两个数x,y表示一对询问。
     
     

    Output

     

    共M行,第i行一个正整数表示第i个询问的结果。

    Sample Input

    3 3
    1 4 3
    0 1
    0 1
    4 3


    Sample Output

    5
    7
    7

    HINT



    HINT

    N=12000,M=6000,x,y,Ai在signed longint范围内。

    Source

    【分析】
    第一次写可持久化trie,还有点问题。
    题解网上都是...先不说了
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <vector>
      6 #include <utility>
      7 #include <iomanip>
      8 #include <string>
      9 #include <cmath>
     10 #include <queue>
     11 #include <assert.h>
     12 #include <map>
     13 
     14 const int N = 12000 + 10;
     15 const int SIZE = 111;//块状链表的根号50000 
     16 const int M = 50000 + 5;
     17 using namespace std;
     18 typedef long long ll;
     19 struct Node{
     20        int val;//代表数量
     21        int num;//代表值
     22        Node *ch[2]; 
     23 }mem[N * 31 * 10], *root[N];
     24 int n, m;//n为数量,m为操作次数 
     25 struct BLOCK_LIST{//块状链表 
     26        int data[SIZE];
     27        int size, next;
     28        void init(){
     29             size = 0;
     30             memset(data, 0, sizeof(data));
     31             next = -1;
     32        }
     33 }list[SIZE];
     34 int tot = 0;//记录mem使用空间 
     35 int Max[SIZE + 10][SIZE + 10], Pos;//表示从i到j块的最大异或值 
     36 int data[N];
     37 
     38 Node *NEW(){//创建新trie节点
     39      Node *p = &mem[tot++];
     40      p->val = p->num = 0;
     41      p->ch[0] = p->ch[1] = NULL;
     42      return p; 
     43 }
     44 void insert(Node *&p, Node *&last, int x){//k为根 
     45      p = NEW();
     46      
     47      Node *u = p, *a = last;
     48      for (int i = 30; i >= 0 ; i--){
     49          int t = (((1 << i) & x) == 0 ? 0 : 1);
     50          if (u->ch[t] == NULL){
     51             u->ch[t] = NEW();
     52             u->ch[t]->val = t;
     53             u->ch[t]->num = a->ch[t]->num + 1;
     54          }
     55          u->ch[t ^ 1] = a -> ch[t ^ 1];
     56          u = u -> ch[t];
     57          a = a -> ch[t];
     58      }
     59      return;
     60 }
     61 int find(Node *&a, Node *&b, int val){
     62     int Ans = 0;
     63     Node *x = a, *y = b; 
     64     for (int i = 30; i >= 0; i--){
     65         
     66         int t = ((((1 << i) & val) == 0 ? 0 : 1) ^ 1);
     67         if (x->ch[t] == NULL || (x->ch[t]->num - y->ch[t]->num) <= 0) t = (t ^ 1);
     68         Ans += (1 << i) * t;
     69         x = x->ch[t];
     70         y = y->ch[t];
     71     }
     72     //Ans += t;
     73     return Ans;
     74 }
     75 
     76 void prepare(){
     77      memset(Max, 0, sizeof( Max ));
     78      Pos = 0;//Pos为块状链表的标号
     79      list[Pos++].init();
     80      insert(root[1], root[0], 0);//插入可持久化trie
     81      for (int cur = 0, i = 1; i <= n; cur = list[cur].next){
     82          int j, M = 0;//M用来记录块的最大值 
     83          for (j = 0; j < SIZE && i <= n; i++, j++){
     84              list[cur].data[j] = data[i];
     85              list[cur].size++;
     86              insert(root[i + 1], root[i], data[i]);//插入可持久化trie
     87              int M2 = data[i];
     88              //M2 = find(root[i + 1], root[cur * SIZE], list[cur].data[j]); 
     89              //printf("%d
    ", M2);
     90              //if (M2 == data[i]) M2 = 0;//显然如果是它自己不如不加即直接从开头一直异或到i
     91              //Max[cur][cur] = M2;
     92              for (int k = Pos - 1; k >= 0; k--){
     93                  int tmp = find(root[i + 1], root[k * SIZE], data[i]);
     94                  //if (tmp == data[i]) tmp = 0;
     95                  if ((M2 ^ data[i]) < (tmp ^ data[i])) M2 = tmp;
     96                  Max[k][cur] = max(Max[k][cur], M2 ^ data[i]);//顺便利用O(sqrt(n))的时间预处理出Max数组 
     97              }
     98          }
     99          //创建新块
    100          if (j == SIZE){
    101             list[Pos].init();
    102             list[cur].next = Pos++;
    103          }
    104      } 
    105      //printf("%d
    ", root[1]->ch[0]->ch[1]->num);
    106 }
    107 int query(int l, int r){
    108      int x = (l - 1) / SIZE, y = (r - 1) / SIZE;//x代表l和r所代表的块
    109      int Ans = 0;
    110      if (x == y){
    111            for (int i = l; i <= r; i++)
    112                Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
    113            return Ans;
    114      }else{
    115            if (x  <= y - 1) Ans = Max[x ][y - 1];
    116            //for (int i = r; i >= l; i--) if ((data[i] ^ data[i - 1]) == 32767) printf("fuck");
    117            for (int i = l; i <= ((x + 1) * SIZE) && i <= n; i++) Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
    118            for (int i = r; i > y * SIZE; i--) Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
    119            return Ans;
    120            //for (int i = l; i <= r; i++)
    121            //    Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
    122            //return Ans;
    123      }
    124 }
    125 //处理询问
    126 void work(){
    127      int last_ans = 0;
    128      for (int i = 1; i <= m; i++){
    129          int x, y, l, r;
    130          scanf("%d%d", &l, &r);
    131          //l--;
    132          //l = min(((ll)((ll)x + (ll)last_ans) % n) + 1 , ((ll)((ll)y + (ll)last_ans) % n)+ 1);
    133          //r = max(((ll)((ll)x + (ll)last_ans) % n) + 1 , ((ll)((ll)y + (ll)last_ans) % n)+ 1);
    134          last_ans = query(l, r);
    135          printf("%d
    ", last_ans);
    136      } 
    137 }
    138 //单纯的插入一个数 
    139 void build(Node *&b, int x){
    140      Node *u = b;
    141      for (int i = 30; i >= 0; i--){
    142          int t = (((1 << i) & x) == 0 ? 0 : 1);//表示这一位是否是0
    143          if (u->ch[t] == NULL){
    144             u->ch[t] = NEW();
    145             u->ch[t]->val = t;
    146             u->ch[t]->num = 0;//注意,这里仅仅只是建树,所以不能改数字 
    147          } 
    148          u = u->ch[t]; 
    149      } 
    150      return;
    151 } 
    152 void init(){
    153      //读入+建初始树 
    154      scanf("%d%d", &n, &m);
    155      for (int i = 0; i < N; i++) root[i] = NULL;
    156      root[0] = NEW();
    157      data[0] = 0;
    158      for (int i = 1; i <= n; i++){
    159          scanf("%d", &data[i]);
    160          data[i] = data[i] ^ data[i - 1];
    161          build(root[0], data[i]);
    162          //printf("%d
    ", data[i]);
    163      }
    164      build(root[0], 0);//记得加0 
    165      //printf("%d", root[0]->val);
    166 }
    167 void debug(){
    168      insert(root[1], root[0], 0);
    169      insert(root[2], root[1], 1);
    170      insert(root[3], root[2], 6);
    171      printf("%d
    ", find(root[3], root[1], 6));
    172 }
    173 
    174 int main(){
    175     #ifdef LOCAL
    176     freopen("data.txt",  "r",  stdin);
    177     freopen("out.txt",  "w",  stdout); 
    178     #endif
    179     init();
    180     prepare();
    181     work();
    182     printf("%d
    ", tot);
    183     //debug();
    184     return 0;
    185 }
    View Code
  • 相关阅读:
    java web设置全局context参数
    tomcat ider配置
    JDBC Druid式link
    JDBC c3p0
    JDBCUtils 工具类
    顺序栈
    线性表链式存储结构的实现的使用
    线性表顺序存储结构的实现和运用
    Mat类下的data指针的深刻理解
    Mat类下几个属性的理解
  • 原文地址:https://www.cnblogs.com/hoskey/p/4324766.html
Copyright © 2020-2023  润新知