只有样例过了,救救孩子吧
查看原帖
只有样例过了,救救孩子吧
1127749
Longerdoc楼主2024/10/31 01:29
#include <algorithm>
#include <vector>
using namespace std;

const int N = 1e5 + 100;
const int NUM = 30; // 根据数据范围变化
const int M = N * (NUM + 1);

int root1[M],  root2[M], max_id[M]; // root记录版本号,Max_Id是当前节点在区间哪个位置
int tr11 [M][2];
int tr2 [M][2];
long long int idx;
int h[N*2];
int e[N * 2];
int ne[N * 2];
int add_idx;
int w[N + 100];
bool st[N*2]; // 记录节点是否被访问过,访问过则标记为true
int dfc;
int in[N*2], out[N*2];
int depth[N*2];
int f[N*2][25];
int lg[N*2];
int val[N*2];
// a所对应的单链表中插入b  a作为根
void add(int a, int b) {
    e[add_idx] = b, ne[add_idx] = h[a], h[a] = add_idx++;
}
void l_dfs(int now, int fath) {
    f[now][0] = fath;
    depth[now] = depth[fath] + 1;
    for (int i = 1; i <= lg[depth[now]]; ++i)
        f[now][i] = f[f[now][i - 1]][i - 1];
    for (int i = h[now]; i != -1; i = ne[i]) {
        if (e[i] != fath) l_dfs(e[i], now);
    }
}

int _query(int x, int y) {
    if (depth[x] < depth[y]) swap(x, y);
    while (depth[x] > depth[y])
        x = f[x][lg[depth[x] - depth[y]] - 1];
    if (x == y) return x;
    for (int i = lg[depth[x]] - 1; i >= 0; i--) {
        if (f[x][i] != f[y][i])
            x = f[x][i],
            y = f[y][i];
    }
    return f[x][0];
}
void insert(int j, int k, int p, int q, int(*tr)[2]) {
    if (k < 0) {
        max_id[q] = in[j];
       // cout << max_id[q] << ";" << endl;;
        return;
    }
    // cout << tr[1][1]; // 输出调试信息
   int   s = w[j];
    int v = ((s >> k) & 1); // 获取当前位的值(0 或 1)
    if (p) tr[q][v ^ 1] = tr[p][v ^ 1]; // 如果 p 不为 0,复制 p 的另一个子节点到 q
    // cout << "hello"; // 输出调试信息
    tr[q][v] = ++idx; // 创建新节点并更新 tr[q][v]
    insert(j, k - 1, tr[p][v], tr[q][v], tr); // 递归插入剩余的位
    max_id[q] = max(max_id[tr[q][1]], max_id[tr[q][0]]); // 更新 max_id[q]
}

void dfs(int u, int fa) {
    root2[u] = ++idx;
    in[u] = ++dfc;
    val[in[u]] = w[u];
    root1[dfc] = ++idx;
    root2[u]=++idx;
     insert(u, NUM, root2[fa], root2[u], tr2);
   // cout << u << ",";
    insert(u, NUM, root1[dfc - 1], root1[dfc], tr11);
    for (int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        if (!st[j]) {
            st[j] = true;
            dfs(j, u);
        }
    }    
    out[u] = dfc; //cout <<u<<" "<<out[u]<< endl;
}

int query(int L, int R, int C, int(*tr)[2]) {
    int p = root1[R];
  //  cout << "r:" << p << endl;
    for (int i = NUM; i >= 0; i--) {
        int v = ((C >> i) & 1);
        //cout << max_id[p] << "."; cout << max_id[tr[p][v ^ 1]] << endl;;
        if (max_id[tr[p][v ^ 1]] >= L) p = tr[p][v ^ 1];
        else p = tr[p][v];
    }
    //cout << max_id[p] << endl;
    //cout << val[max_id[p]] << endl;
    return val[max_id[p]] ^ C;
}
int query2(int L, int R, int C, int(*tr)[2]) {
    int p = root2[R];
    //  cout << "r:" << p << endl;
    for (int i = NUM; i >= 0; i--) {
        int v = ((C >> i) & 1);
        //cout << max_id[p] << "."; cout << max_id[tr[p][v ^ 1]] << endl;;
        if (max_id[tr[p][v ^ 1]] >= L) p = tr[p][v ^ 1];
        else p = tr[p][v];
    }
      //cout << max_id[p] << endl;
     // cout << val[max_id[p]] << endl;
    return val[max_id[p]] ^ C;
}


int main() {
     //ios::sync_with_stdio(false);cin.tie(nullptr);
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 0; i <= 2 * n + 10; i++) h[i] = -1;
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
    }
    for (int i = 1; i <= n - 1; i++) {
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
    }
    for (int i = 1; i <= n; i++) {
        lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
        //	这里存的是logi(以2为底)在加1
            //常数优化
    }
    in[1] = ++idx; 
     max_id[0] = -1; 
     root1[0] = ++idx;
     insert(0, NUM, 0, root1[0], tr11);
     st[1] = true;
    dfs(1, 0);
    l_dfs(1, 0);
   
    root2[0] = ++idx;
  
 
     insert(0, NUM, 0, root2[0], tr2);
    while (m--) {
        int op;
        cin >> op;
       // cout << "dsauid";
        if (op == 1) {
           // cout <<"dasd" << in[6] << endl;
            int x, z;
            cin >> x >> z;
           // cout << in[x] << endl;;
          //  cout << out[x] << endl;
          int ans=max(w[x]^z,query(in[x], out[x], z, tr11) );
            cout<<ans<<endl;
        }
        else {
            int a, b, c;
            cin >> a >> b >> c;
            int x = _query(a, b);
          //  cout << "lac:" << x << endl;
          int ans=max(w[a]^c,w[b]^c);
          ans=max(ans,c^w[x]);
        ans = max(query2(x, a,c,tr2), query2(x, b,c,tr2));
            cout << ans << endl;
        }
    }
    // 将一个区间的异或和处理为前缀和,则两个数的异或则是这个区间的异或和

    // 释放动态分配的内存
  

    return 0;
}```
2024/10/31 01:29
加载中...