题面传送门

又是 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. 从零到熟悉,带你掌握Python len() 函数的使用

    摘要:本文为你带来如何找到长度内置数据类型的使用len() 使用len()与第三方数据类型 提供用于支持len()与用户定义的类. 本文分享自华为云社区<在 Python 中使用 len() 函 ...

  2. HCNP Routing&Switching之BGP路由宣告

    前文我们了解了BGP报文结构.类型以及邻居状态相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15422924.html:今天我们来聊一聊BGP路由宣告 ...

  3. Scrum Meeting 12

    第12次例会报告 日期:2021年06月03日 会议主要内容概述: 介绍了现有进度,wpb介绍了jwt的用法以及部署的swagger的测试用法. 一.进度情况 我们采用日报的形式记录每个人的具体进度, ...

  4. Alpha阶段发布声明

    发布声明 Alpha 1.Alpha版本功能说明 功能列表和详情图 模块 功能 展示 首页 查看首页博文,搜索博文,可供未登录用户使用 动态 查看推荐动态给未登录用户使用,登录用户可以查看关注动态.我 ...

  5. CSDN app分析

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) (北京航空航天大学 - 计算机学院) 这个作业的要求在哪里 个人博客作业-软件案例分析 我的教学班级 005 说说csd ...

  6. 为什么用于开关电源的开关管一般用MOS管而不是三极管

    区别: 1.MOS管损耗比三极管小,导通后压降理论上为0. 2.MOS管为电压驱动型,只需要给电压即可,意思是即便串入一个100K的电阻,只要电压够,MOS管还是能够导通. 3.MOS管的温度特性要比 ...

  7. hdu 5087 Revenge of LIS II (DP)

    题意: N个数,求第二长上升子序列的长度. 数据范围: 1. 1 <= T <= 1002. 2 <= N <= 10003. 1 <= Ai <= 1 000 0 ...

  8. 我为啥开始用CSDN博客

    今晚开通CSDN博客,并且决定以后每天都使用这个不错的东西.与此同时,在博客园也开通了一个:http://www.cnblogs.com/fish7/ 我原本是把做过的题都用WPS整理的,然后每次打印 ...

  9. uni-app使用wx-canvas实现微信小程序上显示地图map和坐标geo

    源码 <template> <view class="echart-box"> <canvas class="ec-canvas" ...

  10. Appium 介绍与环境搭建

    目录 Appium 介绍 APP 自动化测试介绍 什么是 Appium ? Appium 优势 Appium 架构 Appium 生态 Appium 组件 UiAutomator API Bootst ...