社区讨论
orz,求个比较小的样例
P3401洛谷树参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @lo2e1l56
- 此快照首次捕获于
- 2023/10/23 12:19 2 年前
- 此快照最后确认于
- 2023/11/03 12:25 2 年前
CPP
#include <iostream>
#include <bits/stdc++.h>
#define ll long long
using namespace std;
template <typename type>
inline void read(type& x){
x = 0; bool f = 0; char c = getchar();
while(c < '0' || c > '9'){f = c == '-'; c = getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}
if(f) x = -x;
}
const int maxN = 3E4 + 5;
int head[maxN], dfn[maxN], fa[maxN], son[maxN], sz[maxN], top[maxN], depth[maxN], w[maxN], nw[maxN];
int k = 0, cnt = 0;
struct edge{
int to, next;
edge(int to = 0, int next = -1):to(to), next(next){}
}edges[maxN << 1];
struct seg{
ll totS;
int xOr, lc[10], rc[10], len;
seg(ll totS = 0, int xOr = 0, int len = 0):totS(totS), xOr(xOr), len(len){
memset(lc, 0, sizeof(lc));
memset(rc, 0, sizeof(rc));
if(xOr){
for(int i = 0; i < 10; i++){
if((xOr >> i) & 1){
lc[i] ++;
rc[i] ++;
}
}
}
}
}tree[maxN << 2];
inline seg operator+ (const seg& l, const seg& r){
if(!l.len) return r;
if(!r.len) return l;
seg res(0, 0, 0);
res.xOr = l.xOr ^ r.xOr;
res.len = l.len + r.len;
res.totS = l.totS + r.totS;
memcpy(res.lc, l.lc, sizeof(res.lc));
memcpy(res.rc, r.rc, sizeof(res.rc));
for(int i = 0; i < 10; i++){
res.totS += 1ll * (r.lc[i] * l.len + l.rc[i] * r.len - 2 * r.lc[i] * l.rc[i]) * (1 << i);
res.lc[i] += ((l.xOr >> i) & 1)? (r.len - r.lc[i]):r.lc[i];
res.rc[i] += ((r.xOr >> i) & 1)? (l.len - l.rc[i]):l.rc[i];
}
return res;
}
inline void add(int u, int v){
edges[k] = edge(v, head[u]);
head[u] = k++;
}
inline void buildTree(int s, int t, int p){
if(s == t){
tree[p] = seg(nw[s], nw[s], 1);
return ;
}
int m = (t + s) >> 1;
buildTree(s, m, p << 1);
buildTree(m + 1, t, p << 1 | 1);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
inline void dfs1(int now, int f){
fa[now] = f;
depth[now] = depth[f] + 1;
sz[now] = 1;
int maxS = -1;
for(int e = head[now]; ~e; e = edges[e].next){
if(edges[e].to == f) continue;
dfs1(edges[e].to, now);
sz[now] += sz[edges[e].to];
if(sz[edges[e].to] > maxS){
maxS = sz[edges[e].to];
son[now] = edges[e].to;
}
}
}
inline void dfs2(int now, int topf){
top[now] = topf;
dfn[now] = ++cnt;
if(!son[now]) return;
dfs2(son[now], topf);
for(int e = head[now]; ~e; e = edges[e].next){
if(dfn[edges[e].to]) continue;
dfs2(edges[e].to, edges[e].to);
}
}
inline void updata(int x, int v, int s, int t, int p){
if(x == s && x == t){
tree[p] = seg(v, v, 1);
return ;
}
int m = (s + t) >> 1;
if(m >= x){
updata(x, v, s, m, p << 1);
}
else{
updata(x, v, m + 1, t, p << 1 | 1);
}
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
inline seg queryRange(int l, int r, int s, int t, int p){
if(l <= s && r >= t){
return tree[p];
}
int m = (t + s) >> 1;
seg ans(0, 0, 0);
if(m >= l) ans = queryRange(l, r, s, m, p << 1);
if(m < r) ans = ans + queryRange(l, r, m + 1, t, p << 1 | 1);
return ans;
}
inline ll query(int u, int v){
seg l(0, 0, 0), r(0, 0, 0);
while(top[u] != top[v]){
if(depth[top[u]] < depth[top[v]]){
swap(u, v);
swap(l, r);
}
l = queryRange(dfn[top[u]], dfn[u], 1, cnt, 1) + l;
u = fa[top[u]];
}
if(dfn[u] > dfn[v]){
swap(u, v);
swap(l, r);
}
if(dfn[u] < dfn[v]){
l = queryRange(dfn[u] + 1, dfn[v], 1, cnt, 1) + l;
}
ll ans = l.totS + r.totS;
if(l.len && r.len){
for(int i = 0; i < 10; i++){
ans += 1ll * (r.lc[i] * l.len + l.lc[i] * r.len - 2 * r.lc[i] * l.lc[i]) * (1 << i);
}
}
return ans;
}
int main(){
int n, q, u, v, t, wei;
read(n), read(q);
memset(head, -1, sizeof(int) * (n + 1));
memset(dfn, 0, sizeof(int) * (n + 1));
memset(son, 0, sizeof(int) * (n + 1));
memset(nw, 0, sizeof(int) * (n + 1));
for(int i = 0; i < n - 1; i++){
read(u), read(v), read(w[i]);
add(u, v);
add(v, u);
}
nw[1] = 0;
depth[0] = 0;
dfs1(1, 0);
dfs2(1, 1);
for(int i = 0; i < n - 1; i++){
nw[max(dfn[edges[i << 1].to], dfn[edges[i << 1 | 1].to])] = w[i];
}
buildTree(1, cnt, 1);
for(int i = 0; i < q; i++){
read(t), read(u), read(v);
if(t == 1){
printf("%lld\n", query(u, v));
}
else{
read(wei);
updata(max(dfn[u], dfn[v]), wei, 1, cnt, 1);
}
}
return 0;
}
25pts,第三个点链长3000多实在调不出来
回复
共 2 条回复,欢迎继续交流。
正在加载回复...