[WC2018] 即时战略

[WC2018] 即时战略

分享一下全局平衡二叉树的做法。

先讲下部分分。

\(n\le 100,T\le 10000\)

\(1\) 开始 DFS,对于当前 \(u\),枚举点 \(v\),如果 \(\text{explore}(u,v)\) 不为 \(fa_u\),则 \(v\)\(u\) 子结点,向 \(v\) 拓展即可。询问次数 \(O(n^2)\),可得 \(20pts\)

\(\texttt{datatype}=2\)

完全二叉树树高 \(O(\log n)\),子树大小之和为 \(O(n\log n)\)。给每个点开一个 vector 记录子树结点。对于 \(u\) 遍历子树结点 \(v\) 并询问 \(\text{explore}(u,v)=p\)。将 \(v\) 加入 \(p\) 的子树。最后 DFS 所有出现过的 \(p\) 即可。询问次数 \(O(n\log n)\),可得 \(35pts\)

\(\texttt{datatype}=1\)

次数是 \(n+\log n\) 的。当前已访问结点必然是一段链 \([l,r]\)随机取一个未访问点 \(u\),询问 \(\text{explore}(l,u)=p\)。如果 \(p\) 已被访问,则不断询问 \(\text{explore}(r,u)\) 拓展链;否则不断询问 \(\text{explore}(l,u)\)。注意更新 \(l,r\)。考虑 “\(p\) 已被访问”发生的次数是期望 \(O(\log n)\) 的。因为期望下 \(r\) 右边的链每次缩短一半。询问次数 \(n+\log n\),可得 \(65pts\)

正解

先随机一个 \(u\),拉出一条 \(1\to u\) 的链。然后再随机一个 \(v\),在链上二分确定它挂在 \(p\)。然后再拉出一条 \(p\to v\) 的链。这些链的深度都是严格递增的,不难想到重链剖分,这样可以做到 \(O(n\log^2n)\) 的询问次数。问题在于我们无法确定哪个是重儿子。如果你做过 「EZEC-8」猜树 加强版,重子树的点总是比较多,我们随机一个点就可以把它所在的子树当作重子树

然而我们要做到 \(O(n\log n)\) 的询问次数。考虑优化在链上二分的过程,把它换成全局平衡二叉树就能做到 \(O(n\log n)\) 了。但是老问题又来了,我们不知道每个点的外挂子树大小。没关系,我们无需建出全局平衡二叉树,每次找到带权重心即可。

注意外挂子树大小 \(sz_i\) 的更新相当于每次跳重链并单点修改,每次要查询重链连续的一段 \([l,r]\),找到第一个位置 \(p\) 满足 \(\sum_{i=l}^psz_i>\frac 12\sum_{i=l}^r sz_i\),然后选取 \(p\) 为重心。

在每条重链上开一个 fhq treap 即可维护。时间复杂度 \(O(n\log^2n)\),询问次数 \(O(n\log n)\),可以通过。

还是比较好写的。细节的注释在代码里:

#include "rts.h"
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ls u<<1
#define rs u<<1|1
#define mid ((l+r)>>1)
#define lp ch[x][0]
#define rp ch[x][1]
int n;
const int N=300005;
mt19937 rd(time(0));
namespace pool{//随机池int tr[4*N];void build(int l,int r,int u){tr[u]=r-l+1-(l==1);if(l==r) return;build(l,mid,ls),build(mid+1,r,rs);}void del(int l,int r,int u,int p){if(l==r) {tr[u]=0;return;}p<=mid?del(l,mid,ls,p):del(mid+1,r,rs,p);tr[u]=tr[ls]+tr[rs];}int kth(int l,int r,int u,int k){if(l==r) return l;if(k<=tr[ls]) return kth(l,mid,ls,k);return kth(mid+1,r,rs,k-tr[ls]);}void bk(int u){del(1,n,1,u);}//删除已访问点int get(){return kth(1,n,1,rd()%tr[1]+1);}//随机一个未访问点
}
namespace ghf{//链int l[N],r[N];void lk(int x,int y){r[x]=y,l[y]=x;}void solve(){int nl=1,nr=1;while(pool::tr[1]){int u=pool::get(),v;if((v=explore(nl,u))==r[nl]){while(nr!=u){v=explore(nr,u),lk(nr,v),nr=v,pool::bk(v);}}else{lk(v,nl),nl=v,pool::bk(v);while(nl!=u) v=explore(nl,u),lk(v,nl),nl=v,pool::bk(v);}}}
}
namespace thy{int fa[N],son[N],top[N],bot[N],goal,dep[N],lst;//fa[u]:父结点,son[u]:重儿子,top[u]:重链链顶,bot[u]:重链链底,goal:随机出来的 u,dep[u]:深度,lst:上一个点int idx,rt[2*N],tr[N],val[N],sz[N],p[N],ch[N][2];//idx:分配临时根,rt[u]:平衡树根结点,tr[u]:平衡树子树外挂子树大小和,val[u]:u 的外挂子树大小,sz[u]:平衡树子树结点数,p[u]:随机优先值,ch[u][0/1]:左右儿子void up(int x){//fhq treaptr[x]=tr[lp]+tr[rp]+val[x];sz[x]=sz[lp]+sz[rp]+1;}int merge(int x,int y){if(!x||!y) return x+y;if(p[x]<p[y]) return rp=merge(rp,y),up(x),x;return ch[y][0]=merge(x,ch[y][0]),up(y),y;}void split(int x,int &l,int &r,int k){//分裂为排名 [1,k],[k+1,n]if(!x){l=r=0;return;}if(sz[lp]+1<=k) l=x,split(rp,rp,r,k-sz[lp]-1);else r=x,split(lp,l,lp,k);up(x);}void add(int x,int k,int w){if(sz[lp]+1<k) add(rp,k-sz[lp]-1,w);else if(k<=sz[lp]) add(lp,k,w);else val[x]+=w;up(x);}int findrt(int x,int k){//找到第一个前缀和 >=k 的点if(k>tr[lp]+val[x]) return findrt(rp,k-(tr[lp]+val[x]));if(k<=tr[lp]) return findrt(lp,k);return x;}int GBT(int u,int up,int dn){//全局平衡二叉树(动态找重心)int g=findrt(rt[u],(tr[rt[u]]+1)/2),to=explore(g,goal),res;//g 为带权重心if(top[to]==u){//仍在重链里if(dep[to]>dep[g]){//往下找split(rt[u],rt[++idx],rt[u],dep[g]-dep[up]+1);res=GBT(u,son[g],dn),rt[u]=merge(rt[idx--],rt[u]);//回溯,把分裂出去的点合并回来}else{//往上找split(rt[u],rt[u],rt[++idx],dep[g]-dep[up]);res=GBT(u,up,fa[g]),rt[u]=merge(rt[u],rt[idx--]);}}else res=to,lst=g;return res;}void upd(int x,int w){//跳重链更新 valwhile(x){add(rt[top[x]],dep[x]-dep[top[x]]+1,w);x=fa[top[x]];}}void solve(){rt[top[1]=bot[1]=1]=1,idx=n;p[1]=rand(),sz[1]=val[1]=tr[1]=1;while(pool::tr[1]){goal=pool::get();int nw=1;while(nw=GBT(nw,nw,bot[nw]),top[nw]);fa[nw]=lst,dep[nw]=dep[lst]+1;val[nw]=tr[nw]=sz[nw]=1,p[nw]=rand(),rt[nw]=nw;if(top[lst]==bot[top[lst]]){//lst 还没有重儿子,把 nw 定为重儿子top[nw]=top[lst],bot[top[nw]]=nw,son[lst]=nw;rt[top[nw]]=merge(rt[top[nw]],rt[nw]);}else top[nw]=bot[nw]=nw;//另开一条重链pool::bk(nw);int w=1;while(nw!=goal){//拉出一条 nw->goal 的链lst=nw,nw=explore(nw,goal),w++,pool::bk(nw);dep[nw]=dep[lst]+1,fa[nw]=lst,son[lst]=nw,top[nw]=top[lst],bot[top[nw]]=nw;val[nw]=tr[nw]=sz[nw]=1,p[nw]=rand(),rt[nw]=nw;rt[top[nw]]=merge(rt[top[nw]],rt[nw]);}upd(fa[top[nw]],w);}}
}
void play(int num, int T, int dataType) {srand(time(0));n=num,pool::build(1,n,1);if(dataType==3) ghf::solve();//链的限制比较紧,特判else thy::solve();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927485.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

商城网站源码大全微网站建站

怎么解决java导出excel时文件名乱码发布时间&#xff1a;2020-06-19 16:59:00来源&#xff1a;亿速云阅读&#xff1a;137作者&#xff1a;元一java解决导出Excel时文件名乱码的方法示例&#xff1a;String agent request.getHeader("USER-AGENT").toLowerCase();re…

实用指南:Unity学习之C#的反射机制

实用指南:Unity学习之C#的反射机制pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco…

电子政务网站建设参考文献wdcp 网站打不开

一金融机构在近期发生了一起数据泄露事件。 经过调查&#xff0c;发现是由于一名员工将包含客户敏感信息的文件通过电子邮件发送给了未经授权的第三方。 这一事件导致客户数据泄露&#xff0c;给该机构带来了严重的声誉损失和信任危机。 这一案例凸显了数据防泄漏系统的重要性…

网站开发 数据库深圳制作网站

1、背景介绍 重装win10系统&#xff0c;重装Python。在坑出现之前&#xff0c;已经完成了Python的安装&#xff08;D盘&#xff09;&#xff0c;并且在系统中添加了环境变量。由于平时需要用到Python2.7和Python3.6&#xff0c;这里将对应的解释器分别改名为Python2和Python3。…

HDF5文件 ——之三

H5G、H5L、H5O 是 HDF5 C API 的分组接口,在 HDF.PInvoke.NETStandard(C# 的 HDF5 封装包)里,它们分别代表 HDF5 底层 对象层(Object layer)、组层(Group layer) 和 链接层(Link layer) 的操作模块。🧱 一…

MySQL库的操作(ubuntu) - 教程

MySQL库的操作(ubuntu) - 教程2025-10-04 19:34 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importan…

创业做社交网站有哪些做一个网站 多少钱

1&#xff09;熟悉之前的SysUser登录流程 过滤器链验证配置 这里security过滤器链增加了前置过滤器链jwtFilter 该过滤器为我们自定义的&#xff0c;每次请求都会经过jwt验证 ok我们按ctrl alt B跳转过去来看下 首先会获取登录用户LoginUser 内部通过header键&#xff0c;获…

代码随想录算法训练营|Day 25

Day 25 第七章 回溯算法 part04 491.递增子序列 本题和大家刚做过的 90.子集II 非常像,但又很不一样,很容易掉坑里。 https://programmercarl.com/0491.递增子序列.html 视频讲解:https://www.bilibili.com/video/B…

深入解析:SAE J3072-2024插电式电动汽车(PEV)中的车载逆变器系统安全标准介绍

深入解析:SAE J3072-2024插电式电动汽车(PEV)中的车载逆变器系统安全标准介绍pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-…

冷僻模板整理

min25筛 可以低于线性的解决1到N中的质数的k次幂的求和的问题,并且在处理了N之后对于1到N中数论分块所需的点x(l,r)都可以通过val=g[ID(x)]以O(1)的代价获取到 如果不需要多次查询,建议把命名空间外的定义放到m…

参考文献网站开发电商网站平台有哪些功能

1、Lambda表达式 Lambda表达式是Java8的新特性。 组成Lambda表达式的三个要素&#xff1a;形式参数&#xff0c;箭头操作符&#xff0c;代码块 Lambda表达式的格式&#xff1a;(形式参数) -> {代码块} //如&#xff1a;(int a, int b) -> {return a b;}形式参数&…

深入解析:精读C++20设计模式——行为型设计模式:命令模式

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Apache Beam入门教程:统一批流处理模型 - 教程

Apache Beam入门教程:统一批流处理模型 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

详细介绍:关于[汉芝电子低调获取证书,及生产各类加密产品]这档事

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

中国建设银行网站首页joy怎样添加字体到wordpress

目录 ★ 工作队列介绍代码演示测试注意点1&#xff1a;注意点2&#xff1a; ★ 工作队列介绍 工作队列&#xff1a; 就是让多个消费者竞争消费同一个消息队列的消息&#xff0c;相当于多个消费者共享消息队列。 ▲ RabbitMQ可以让多个消费者竞争消费同一个消息队列 ▲ 消息队…

华梦服饰网站建设中wordpress临时关闭站点

&#xff08;四&#xff09;无人机技术 1.无人作战飞机1.1 美国空军披露可与下一代战斗机编组作战的协同式无人作战飞机项目1.2 俄罗斯无人作战飞机取得重要进展 2.支援保障无人机2.1 欧洲无人机项目通过首个里程碑2.2 美国海军继续开展MQ-25无人加油机测试工作 3.微小型无人机…

花卉物流园做网站的素材phpcms做网站建栏目

1.关注点分离&#xff1a;每个功能最少会被切分为M-V-C三个部分&#xff0c;让开发者一次只需要关注一个部分&#xff0c;进而降低复杂难度&#xff0c;提高开发效率2.分层负责&#xff1a;明确切割&#xff0c;M-V-C三个部分并行开发3.自由操控HTML&#xff1a;在ASP.Net MVC中…

网站建设技术难题物流推广做哪个网站

在3dMax中如何把三维物体转化为由样条线构成的对象&#xff1f;通常这样的场景会出现在科研绘图或一些艺术创作当中&#xff0c;下面给大家详细讲解一种3dmax三维物体转样条线的方法。 第一部分&#xff1a;用粒子填充3D对象&#xff1a; 1.创建一个三维对象&#xff08;本例…

自适应h5网站模板wordpress wordcloud

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇利用OpenCV4.9制作自己的线性滤波器&#xff01; 下一篇 :OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 …

C# 与 C/C++ 互操作

本文介绍 C# 与 C/C++ 互操作的方法,尤重点介绍 P/Invoke。本文介绍 C# 与 C/C++ 互操作的方法,尤重点介绍 P/Invoke。 为什么要互操作? 主要有两个原因:用 C/C++ 编写算法核心代码,提高程序性能。 有一些库 / AP…