【洛谷】P3401 洛谷树

这道题目涉及一棵带边权的树,要求支持修改边权和查询指定两点间简单路径上所有子链异或和的和。利用异或的性质,可以将问题转化为求树上异或前缀和,并通过树剖和线段树来一次性统计所有点对的路径异或和。解决方案是计算每个节点到根的异或前缀和,并用树剖配合线段树快速处理每一位上的1和0的数量,进而得到答案。
摘要由CSDN通过智能技术生成

题目大意:
给一棵树,有边权,支持两个操作。
(1)修改一个边权
(2)查询u到v的简单路径的所有子链的异或和的和
https://www.luogu.org/problemnew/show/P3401
做法:
首先这是异或,注意到满足a^b^b = a,
要求所有子链的异或和,即求在(u, v)这个路径上的任意两点(x, y)的路径的异或和之和
考虑处理树上异或前缀和,即sum[i] = i 异或到根,从而sum[i]^sum[j]就是 i 异或到 j
然后发现要求所有的点对,一次一次求肯定会tle,那么考虑如何一次统计所有点对
对于某一位k,只需要求出来所有的前缀和中,这一位是0的有几个,这一位是1的有几个,把这两个乘起来就是组成点对这一位是1的个数,那么进行树剖+线段树即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <algorithm>
#define MAXN 30050
using namespace std;
/*
输入格式:
第一行两个正整数n和q,表示点的个数,查询和询问的总次数。

接下来n-1行,每行两个正整数u、v、w,表示u和v两个点之间有一条边权为w的边。

接下来q行,格式为1 u v或2 u v w。如果为1 u v操作,
你需要输出u到v的路径上所有子路径经过的边的边权的xor值的和是多少;
如果为2 u v w操作,你需要把u到v这条边的边权改为w,保证这条边存在。

输出格式:
对于每个1操作,输出答案。*/
int n, q, son[MAXN], size[MAXN], dep[MAXN], fa[MAXN], top[MAXN], id[MAXN], b[MAXN], num[MAXN], ecnt, tcnt, ed[MAXN]; 
struct node{
    int v, w;
    node *next;
    node(){}
    node(int _v, int _w, node *_n) {
        v = _v, w = _w, next = _n;
    }
}pool[MAXN<<2], *h[MAXN];
struct node2{
    int num0, num1, rev;
    node2 operator + (const node2 &x){
        node2 t;
        t.num0 = num0 + x.num0;
        t.num1 = num1 + x.num1;
        t.rev = 0;
        return t;
    }
}t[25][MAXN<<3];
inline void addedge(int u, int v, int w){
    node *p1 = &pool[ecnt++], *p2 = &pool[ecnt++];
    *p1 = node(v, w, h[u]), h[u] = p1;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值