• 【树上倍增】【lca】计蒜客


    https://nanti.jisuanke.com/t/17120

    求一棵树上u到v路径上距离间隔k的元素的异或和。不错的题,稍后编辑

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn = 100010, MOD = 1e9+7, M = 18, K = 63;
      5 int n,q,a[maxn],dep[maxn],fa[maxn][M+2],sum[maxn][K+2];
      6 vector<vector<int>> G(maxn);
      7 
      8 int lca(int u,int v){
      9     if(dep[u] > dep[v]) swap(u,v);
     10     int d = dep[v] - dep[u];
     11     for(int i = 0;i <= M;++i)
     12         if(d >> i & 1) v = fa[v][i];
     13     if(u == v) return v;
     14     for(int i = M; ~i; --i){
     15         if(fa[u][i] != fa[v][i]){
     16             u = fa[u][i];
     17             v = fa[v][i];
     18         }
     19     }
     20     return fa[v][0];
     21 }
     22 
     23 int fnd(int v,int k){
     24     int tmp = 0;
     25     while(k){
     26         if(k & 1) v = fa[v][tmp];
     27         k >>= 1;
     28         tmp++;
     29     }
     30     return v;
     31 }
     32 
     33 void dfs(int v,int pre){
     34     fa[v][0] = pre;
     35     for(auto x: G[v]){
     36         if(x == pre) continue;
     37         dep[x] = dep[v] + 1;
     38         dfs(x,v);
     39     }
     40 }
     41 
     42 void dfs2(int v,int pre){
     43     for(int i = 1;i <= K;++i)
     44         sum[v][i] = sum[fnd(v,i)][i] ^ a[v];
     45     for(auto x: G[v]){
     46         if(x == pre) continue;
     47         dfs2(x,v);
     48     }
     49 }
     50 
     51 void init(){
     52     dfs(1,0);
     53     for(int i = 1;i <= M;++i)
     54         for(int j = 1;j <= n;++j)
     55             fa[j][i] = fa[fa[j][i-1]][i-1];
     56     dfs2(1,0);
     57 }
     58 
     59 int query(int u,int v,int k){
     60     int l = lca(u,v), now = u, ans = 0;
     61     if(k <= K){
     62         int x = (dep[u] - dep[l]) / k;
     63         int t = fnd(u,x*k+k);
     64         ans ^= sum[u][k];
     65         ans ^= sum[t][k];
     66         x = dep[l] + k - ((dep[u] - x * k) - dep[l]);
     67         if(x <= dep[v]){
     68             int tmp = dep[v] - x;
     69             now = fnd(v,tmp % k);
     70             ans ^= sum[now][k];
     71             t = fnd(v,tmp+k);
     72             ans ^= sum[t][k];
     73         }
     74     }
     75     else{
     76         for(;;){
     77             ans ^= a[now];
     78             if(dep[now] - k < dep[l]) break;
     79             now = fnd(now,k);
     80         }
     81         int x = dep[l] + k - (dep[now] - dep[l]);
     82         if(x <= dep[v]){
     83             int tmp = dep[v] - x;
     84             now = fnd(v,tmp % k);
     85             for(;;){
     86                 ans ^= a[now];
     87                 if(dep[now] - k < x) break;
     88                 now = fnd(now,k);
     89             }
     90         }
     91     }
     92     return ans;
     93 }
     94 
     95 int main(){
     96     while(~scanf("%d%d",&n,&q)){
     97         for(int i = 1;i <= n;++i) G[i].clear();
     98         for(int i = 1;i < n;++i){
     99             int u, v;
    100             scanf("%d%d",&u,&v);
    101             G[u].push_back(v);
    102             G[v].push_back(u);
    103         }
    104         for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
    105         init();
    106         while(q--){
    107             int u,v,k;
    108             scanf("%d%d%d",&u,&v,&k);
    109             printf("%d
    ",query(u,v,k));
    110         }
    111     }
    112 
    113     return 0;
    114 }
  • 相关阅读:
    docker mysql
    dotnet core webapi +vue 搭建前后端完全分离web架构
    npm run dev
    docker pureftpd
    虚拟主机连接FTP发送"AUTH TLS"命令后提示“无法连接到服务器”
    [mobile开发碎碎念]手机页面上显示PDF文件
    T-SQL注意事项(1)——SET NOCOUNT ON的去与留
    Tomcat 部署多个项目出现错误
    十进制小数和二进制小数之间的转换
    sed 替换多个空格为一个
  • 原文地址:https://www.cnblogs.com/doub7e/p/7560080.html
Copyright © 2020-2023  润新知