题面传送门

又是 ix35 神仙出的题,先以 mol 为敬 %%%

首先预处理出根节点到每个点路径上权值的异或和 \(dis_i\),那么两点 \(a,b\) 路径上权值的异或和显然为 \(dis_a\oplus dis_b\)。

我们考虑探究 \(a,b\) 与 \(c,d\) 间的路径不相交意味着什么。记 \(l=lca(a,b)\),显然 \(c,d\) 不能一个在 \(l\) 子树内,一个在 \(l\) 子树外,否则它们间的路径就会经过 \(l\) 了。那么分两种情况,\(c,d\) 全在 \(l\) 子树外,和 \(c,d\) 全在 \(l\) 子树内。\(c,d\) 全在子树外的情况显然好搞定,只要 \(c,d\) 都在 \(l\) 的子树外,那么 \(a,b\) 与 \(c,d\) 之间的路径就肯定不会相交。比较麻烦的是 \(c,d\) 全在 \(l\) 子树内的情况,记 \(l'=lca(c,d)\),显然 \(l'\neq l\),而 \(c,d\) 都在 \(l\) 子树内,故 \(l'\) 也在 \(l\) 子树内,如果我们交换 \((a,b)\) 和 \((c,d)\),那么可得 \(c,d\) 的 lca 在 \(a,b\) 的 lca \(l'\) 的子树外,故第二种情况可以规约到第一种情况。所以我们只用考虑第一种情况就行了。

考虑枚举 \(a,b\) 的 lca \(l\),如果我们按照 DFS 序将原树展开成一个序列,那么相当于在 \([dfn_l,dfn_l+sz_l-1]\) 和 \([1,dfn_l-1]\cup[dfn_l+sz_l,n]\) 中分别选择两个数 \(a,b\) 和 \(c,d\) 使得 \(dis_a\oplus dis_b+dis_c\oplus dis_d\) 最大。那么我们只用让它们分别最大即可。而如果我们令 \(dfn_i=dfn_{i-n}(i>n)\),那么后面那个区间并又可写成 \([dfn_l+sz_l,dfn_l+n-1]\)。于是现在题目转化为:给定一个序列 \(a\),要求在 \([l,r]\) 中选择两个数 \(a_i,a_j\),\(a_i\oplus a_j\) 的最大值。首先可以肯定的是这东西没法用 DS 直接维护,而本题 3e4 的数据范围也在疯狂暗示本题的根号算法。故考虑莫队,建立一个 01-trie,插入某个数 \(x\) 的时候就按照套路将其插入 01-trie,而本题的答案以取 \(\max\) 出现的,不支持删除。故使用回滚莫队,扫到右端点的时候记录一个 \(tmp\) 保存答案,解决一个询问之后就用临时保存的值还原答案即可。

时间复杂度 \(n\sqrt{n}\log w\)

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=3e4;
const int SQRT=245;
const int LOG_N=30;
const int MAXP=1e6;
int n,hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],cst[MAXN*2+5],ec=0;
void adde(int u,int v,int w){to[++ec]=v;cst[ec]=w;nxt[ec]=hd[u];hd[u]=ec;}
int dis[MAXN+5],dfn[MAXN+5],ed[MAXN+5],id[MAXN+5],tim=0;
void dfs(int x,int f){
dfn[x]=++tim;id[tim]=x;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=cst[e];if(y==f) continue;
dis[y]=dis[x]^z;dfs(y,x);
} ed[x]=tim;
}
int blk_sz,blk_cnt,L[SQRT+5],R[SQRT+5],bel[MAXN*2+5];
int w[MAXN*2+5];
struct query{
int l,r,id;
bool operator <(const query &rhs){
if(bel[l]!=bel[rhs.l]) return l<rhs.l;
return r<rhs.r;
}
} q[MAXN*2+5];
int ch[MAXP+5][2],siz[MAXP+5],ncnt=0;
void insert(int x,int v){
int cur=0;
for(int i=LOG_N;~i;i--){
int d=x>>i&1;
if(!ch[cur][d]) ch[cur][d]=++ncnt;
cur=ch[cur][d];siz[cur]+=v;
}
}
int query(int v){
int x=0,cur=0;
for(int i=LOG_N;~i;i--){
int d=v>>i&1;
if(siz[ch[cur][d^1]]) x|=1<<i,cur=ch[cur][d^1];
else cur=ch[cur][d];
} return x;
}
int ans=0,res[MAXN+5];
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v,w;scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);adde(v,u,w);
} dfs(1,0);
for(int i=1;i<=n;i++) w[i]=dis[id[i]];
for(int i=n+1;i<=n*2;i++) w[i]=w[i-n];
// for(int i=1;i<=n*2;i++) printf("%d\n",w[i]);
blk_sz=(int)sqrt(2*n);blk_cnt=(2*n-1)/blk_sz+1;
for(int i=1;i<=blk_cnt;i++){
L[i]=(i-1)*blk_sz+1;
R[i]=min(i*blk_sz,2*n);
for(int j=L[i];j<=R[i];j++) bel[j]=i;
}
for(int i=2;i<=n;i++){
q[i-1].l=dfn[i];q[i-1].r=ed[i];q[i-1].id=i;
q[i+n-2].l=ed[i]+1;q[i+n-2].r=dfn[i]+n-1;q[i+n-2].id=i;
// printf("%d %d %d\n",dfn[i],ed[i],i);
// printf("%d %d %d\n",ed[i]+1,dfn[i]+n-1,i);
} sort(q+1,q+(n<<1)-1);int cl=1,cr=0;
// for(int i=1;i<=(n<<1)-2;i++) printf("%d %d %d\n",q[i].l,q[i].r,q[i].id);
for(int i=1;i<=(n<<1)-2;i++){
if(i==1||bel[q[i].l]!=bel[q[i-1].l]){
cl=R[bel[q[i].l]]+1;cr=cl-1;
memset(siz,0,sizeof(siz));memset(ch,0,sizeof(ch));
ncnt=0;ans=0;
}
if(bel[q[i].l]==bel[q[i].r]){
int mx=-0x3f3f3f3f;
for(int j=q[i].l;j<=q[i].r;j++) insert(w[j],1);
for(int j=q[i].l;j<=q[i].r;j++) mx=max(mx,query(w[j]));
for(int j=q[i].l;j<=q[i].r;j++) insert(w[j],-1);
res[q[i].id]+=mx;continue;
}
while(cr<q[i].r) insert(w[++cr],1),ans=max(ans,query(w[cr]));
int tmp=ans;
while(cl>q[i].l) insert(w[--cl],1),ans=max(ans,query(w[cl]));
res[q[i].id]+=ans;
while(cl<R[bel[q[i].l]]+1) insert(w[cl++],-1);
ans=tmp;
} int mx=0;
for(int i=1;i<=n;i++) chkmax(mx,res[i]);
printf("%d\n",mx);
return 0;
}

洛谷 P6072 -『MdOI R1』Path(回滚莫队+01-trie)的更多相关文章

  1. P6072 『MdOI R1』Path

    考虑我们有这样操作. 我们只要维护两点在子树内和两点在子树外的异或和即可. 前者可以类似于线段树合并的trie树合并. 后者有两种做法: 一种是把dfn序翻倍:然后子树补变成了一个区间最大异或问题,可 ...

  2. 洛谷 P6071 『MdOI R1』Treequery(LCA+线段树+主席树)

    题目链接 题意:给出一棵树,有边权,\(m\) 次询问,每次给出三个数 \(p,l,r\),求边集 \(\bigcap\limits_{i=l}^rE(p,i)\) 中所有边的权值和. 其中 \(E( ...

  3. 洛谷 P6383 -『MdOI R2』Resurrection(DP)

    洛谷题面传送门 高速公路上正是补 blog 的时候,难道不是吗/doge,难不成逆在高速公路上写题/jy 首先形成的图显然是连通图并且有 \(n-1\) 条边.故形成的图是一棵树. 我们考虑什么样的树 ...

  4. 【洛谷3674】小清新人渣的本愿(莫队,bitset)

    [洛谷3674]小清新人渣的本愿(莫队,bitset) 题面 洛谷,自己去看去,太长了 题解 很显然的莫队. 但是怎么查询那几个询问. 对于询问乘积,显然可以暴力枚举因数(反正加起来也是\(O(n\s ...

  5. 【洛谷5398】[Ynoi2018]GOSICK(二次离线莫队)

    题目: 洛谷 5398 当我刚学莫队的时候,他们告诉我莫队能解决几乎所有区间问题: 现在,当我发现一个区间问题似乎难以用我所了解的莫队解决的时候,他们就把这题的正解叫做 XXX 莫队.--题记 (以上 ...

  6. 洛谷P4689 [Ynoi2016]这是我自己的发明 [莫队]

    传送门 ynoi中比较良心不卡常的题. 思路 没有换根操作时显然可以变成dfs序莫队随便搞. 换根操作时一个子树可以变成两段区间的并集,也随便搞搞就好了. 这题完全不卡常,随便过. 代码 #inclu ...

  7. 洛谷 P1494 [国家集训队]小Z的袜子(莫队)

    题目链接:https://www.luogu.com.cn/problem/P1494 一道很经典的莫队模板题,然而每道莫队题的大体轮廓都差不多. 首先莫队是一种基于分块的算法,它的显著特点就是: 能 ...

  8. 『MdOI R1』Treequery

    我们可以思考怎么做呢. 首先我们需要进行一些分类讨论: 我们先思考一下如果所有关键点都在 \(p\) 的子树内, 那显然是所有关键点的 \(Lca\) 到 \(p\) 距离. 如果所有关键点一些在 \ ...

  9. 【洛谷】1972:[SDOI2009]HH的项链【莫队+树状数组】

    P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含 ...

随机推荐

  1. 面试题 08.12. N皇后

    题目 设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行.不同列,也不在对角线上.这里的"对角线"指的是所有的对角线,不只是平分整个棋盘的那两条对角 ...

  2. Java版人脸检测详解上篇:运行环境的Docker镜像(CentOS+JDK+OpenCV)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. BUAA 2020 软件工程 提问回顾与个人总结

    BUAA 2020 软件工程 提问回顾与个人总结 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 提问回顾 ...

  4. Vue 报错Error in render: “TypeError: Cannot read properties of null (reading ‘xxx’)” found in

    前端vue报错 [Vue warn]: Error in render: "TypeError: Cannot read properties of null (reading 'name' ...

  5. 状压dp学习笔记(紫例题集)

    P3451旅游景点 Tourist Attractions 这个代码其实不算是正规题解的(因为我蒟蒻)是在我们的hzoj上内存限制324MIB情况下过掉的,而且经过研究感觉不太能用滚动数组,所以那这个 ...

  6. 【代码更新】单细胞分析实录(20): 将多个样本的CNV定位到染色体臂,并画热图

    之前写过三篇和CNV相关的帖子,如果你做肿瘤单细胞转录组,大概率看过: 单细胞分析实录(11): inferCNV的基本用法 单细胞分析实录(12): 如何推断肿瘤细胞 单细胞分析实录(13): in ...

  7. 基于屏幕空间的实时全局光照(Real-time Global Illumination Based On Screen Space)

    目录 Reflective Shadow Maps(RSM) RSM 的重要性采样 RSM 的应用与缺陷 Screen Space Ambient Occulsion(SSAO) SSAO Blur ...

  8. 图像原始格式(YUV444 YUV422 YUV420)一探究竟

    前段时间搞x264编码测试,传参的时候需要告诉编码器我的原始数据格式是什么,其中在x264.h头文件中定义了如下一堆类型. /* Colorspace type */ #define X264_CSP ...

  9. Python matplotlib 概率论与数理统计 伯努利分布 二项分布

    Python 代码实现 二项分布 import numpy as np import matplotlib.pyplot as plt import math from scipy import st ...

  10. hdu 3887 Counting Offspring(DFS序【非递归】+树状数组)

    题意: N个点形成一棵树.给出根结点P还有树结构的信息. 输出每个点的F[i].F[i]:以i为根的所有子结点中编号比i小的数的个数. 0<n<=10^5 思路: 方法一:直接DFS,进入 ...