列表

详情


NC200191. XORTREE

描述

    给出一颗个结点条边的带权树,第个结点的权值为 
    定义点到点的路径的长度为点到点的最短路径上的所有结点的权值的异或和。
    单独一个点不算做路径。
    现在要求你维护个操作:
          将点的权值修改为
        求点到点之间的所有子路径的长度的异或和

输入描述

第一行两个整数
第二行n个整数表示
接下来n-1行每行两个整数表示之间有一条边
接下来q行每行三个整数表示一个查询,数据保证对于查询,满足

输出描述

对于每个查询输出一行一个整数表示答案

示例1

输入:

5 3
1 2 3 4 5
1 2
2 3
3 4
4 5
2 1 5
1 2 8
2 1 5

输出:

6
12

说明:

{f(u,v)}表示点{u}到点{v}最短路径上所有结点的权值的异或和,那么第一个查询的答案为:
{f(1,2)\bigoplus f(1,3)\bigoplus f(1,4)\bigoplus f(1,5)\bigoplus f(2,3)\bigoplus f(2,4)\bigoplus f(2,5)\bigoplus f(3,4)\bigoplus f(3,5)\bigoplus f(4,5)=6}
其中{f(1,4)=1\bigoplus 2\bigoplus 3\bigoplus 4,f(2,5)=2\bigoplus 3\bigoplus 4\bigoplus 5},其它的类似。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 565ms, 内存消耗: 118908K, 提交时间: 2023-07-10 18:49:39

#include <iostream>
#include <cstring>
#include <vector>

#define int long long

using namespace std;

const int N = 1000010;

int n, m, a[N];
vector<int> adj[N];
int l[N], r[N], fa[N], ts, ts0;
int st[N * 2][20], lg[N * 2];
int first[N], dep[N];

void dfs(int u, int father) {
  fa[u] = father; 
  l[u] = ++ts;
  st[++ts0][0] = u, first[u] = ts0;
  dep[u] = dep[father] + 1;
  for (auto v : adj[u]) {
    if (v == father) continue;
    dfs(v, u);
    st[++ts0][0] = u;
  }
  r[u] = ts;
}

int mind(int x, int y) {
  return dep[x] < dep[y] ? x : y;
}
 
int lca(int u, int v) {
  int l = first[u], r = first[v]; 
  if (l > r) swap(l, r);
  int k = lg[r - l + 1];
  return mind(st[l][k], st[r - (1 << k) + 1][k]); 
}

void init() {
  lg[1] = 0;
  for (int i = 2; i <= ts0; i++) lg[i] = lg[i >> 1] + 1;
  for (int j = 1; j < 20; j++)
    for (int i = 1; i + (1 << j) - 1 <= ts0; i++)
      st[i][j] = mind(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
}

struct Fenw {
  int tr[N];
  
  int lowbit(int x) {
    return x & -x;
  }
   
  void add(int x, int v) {
    for (; x <= ts; x += lowbit(x))
      tr[x] ^= v;
  }
  
  void add(int l, int r, int x) {
    add(l, x), add(++r, x);
  }
  
  int ask(int x) {
    int res = 0;
    for (; x; x -= lowbit(x))
      res ^= tr[x];
    return res;
  }
  
} t[2];

signed main() {
  cin.tie(0)->sync_with_stdio(false);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    adj[u].emplace_back(v);
    adj[v].emplace_back(u);
  }
  dfs(1, 0);
  init();
  for (int i = 1; i <= n; i++) {
    t[dep[i] & 1].add(l[i], r[i], a[i]);
  }
  while (m--) {
    int op, u, v;
    cin >> op >> u >> v;
    if (op == 1) {
      t[dep[u] & 1].add(l[u], r[u], a[u] ^ v);
      a[u] = v;
    } else {
      int p = lca(u, v);
      int dist = dep[u] + dep[v] - dep[p] - dep[fa[p]], res = 0;
      if (dist & 1) {
        res ^= t[!(dep[u] & 1)].ask(l[u]) ^ t[!(dep[u] & 1)].ask(l[fa[p]]);
        res ^= t[!(dep[v] & 1)].ask(l[v]) ^ t[!(dep[v] & 1)].ask(l[p]);
      } else {
        for (int i : {0, 1}) {
          res ^= t[i].ask(l[u]) ^ t[i].ask(l[fa[p]]);
          res ^= t[i].ask(l[v]) ^ t[i].ask(l[p]);
        }
      }
      cout << res << '\n';
    }
  }
  return 0;
}

C++14(g++5.4) 解法, 执行用时: 406ms, 内存消耗: 35700K, 提交时间: 2020-03-26 18:28:56

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int n,m,a[N],sz[N],df[N],to[N],son[N],fa[N],cnt,dep[N];
vector<int>v[N];
void dfs1(int o,int pre){
  int s=-1;sz[o]=1;fa[o]=pre;dep[o]=dep[pre]+1;
  for(auto k:v[o]){
    if(k!=pre){
      dfs1(k,o);
      sz[o]+=sz[k];
      if(sz[k]>s){
        s=sz[k];son[o]=k;
      }
    }
  }
}
void dfs2(int o,int t){
  to[o]=t;
  df[o]=++cnt;
  if(son[o])dfs2(son[o],t);
  for(auto k:v[o]){
    if(k==fa[o]||k==son[o])
      continue;
    dfs2(k,k);
  }
}
int T[3][N];
void add(int p,int d,int x){
  for(;p<N;p+=p&-p)T[x][p]^=d;
}
int get(int p,int x){
  int res=0;
  for(;p;p-=p&-p)res^=T[x][p];
  return res;
}
int main() {
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)scanf("%d",a+i);
  for(int i=1;i<n;i++){
    int s,t;
    scanf("%d%d",&s,&t);
    v[s].pb(t);
    v[t].pb(s);
  }
  dfs1(1,0);
  dfs2(1,1);
  for(int i=1;i<=n;i++){
    add(df[i],a[i],dep[i]%2);
    add(df[i],a[i],2);
  }
  for(int i=1;i<=m;i++){
    int ope,l,r;
    scanf("%d",&ope);
    if(ope==1){
      scanf("%d%d",&l,&r);
      add(df[l],a[l]^r,dep[l]%2);
      add(df[l],a[l]^r,2);
      a[l]=r;
    }else{
      scanf("%d%d",&l,&r);
      int sta;
      if(dep[l]%2!=dep[r]%2)sta=2;
      else{
        if(dep[l]&1)sta=0;
        else sta=1;
      }
      int ans=0;
      while(to[l]!=to[r]){
        if(df[l]<df[r])swap(l,r);
        ans^=get(df[to[l]]-1,sta)^get(df[l],sta);
        l=fa[to[l]];
      }
      if(df[l]<df[r])swap(l,r);
      ans^=get(df[r]-1,sta)^get(df[l],sta);
      printf("%d\n",ans);
    }
  }
  return 0;
}

上一题