NOIP2023模拟2联测23 T2 害怕

好像写了一种出题人意料之外的算法。

思路

在生成树上加入白边,白边和若干条蓝色边形成环,环上的蓝色边必须要分配比该白色边更小的边权(最小生成树)。

给每一条边一个分配优先级,优先级的数越小,优先级越高,分配的边权越小。

一开始所有边的优先级的数都等于自己本身的输入顺序。

不断加入白边,与白边形成环的蓝边,优先级有一下两个选择:1.选自己的输入顺序;2.选白边的输入顺序。

每一条边都希望自己分配的边权更小,所以该边会上述选择较小者。

正确性证明:

如果蓝色边边权比白色边小:不做改动,依旧分配之前的边权。

如果蓝色边边权比白色边大:如果不做改动,那么白色边分配的边权要等到,形成环的蓝边边权在原优先级上分配结束,才能分配自己。那么可能会有优先级比白边低的边分配到比白色边更小的值,这肯定是不优的(白色边排序更靠前,边权越低,带来字典序越小)。

这里也可以距离证明一下,正确性是有保证的。

那么维护两点之间路径边的优先级即可,为了方便实现,可以边权压点权,使用树剖。

树剖的线段树维护的是该段内的优先级的分配情况,发现如果从小到大枚举白色边形成环,那么所有的蓝色边的优先级最多被更改一次(或者说只被白色边找到一次,因为后面找到这条蓝边的优先级肯定没有之前的高)。

维护两点路径可以看做求 \(LCA\)。

不过线段树后面被卡时限了,发现求 \(LCA\) 是若干个完整的链加三四个分裂的链,完整的链实际上查过一次就不用查了,可以大大优化复杂度。

线段树实现:

#include<bits/stdc++.h>
using namespace std; #define fi first
#define se second const int maxn=5e5+5; struct node1
{
int to,nxt,id;
}edge[maxn*2];
struct node2
{
int u,v,id;
}ed[maxn]; int n,m,tot,cnt,cok,ct,cdq;
int head[maxn],hso[maxn],sz[maxn],p[maxn],fp[maxn],fa[maxn],top[maxn],ans[maxn],deep[maxn],cis[maxn]; bool vis[maxn]; pair<int,int>dq[maxn]; vector< pair<int,int> >vec[maxn]; inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
inline void write(int X)
{
if(X<0) {X=~(X-1); putchar('-');}
if(X>9) write(X/10);
putchar(X%10+'0');
} inline void add(int x,int y,int z)
{
tot++;
edge[tot].to=y;
edge[tot].nxt=head[x];
edge[tot].id=z;
head[x]=tot;
} inline void dfs1(int u)
{
sz[u]++;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa[u]) continue;
fa[v]=u;
deep[v]=deep[u]+1;
cis[v]=edge[i].id;
dfs1(v);
sz[u]+=sz[v];
if(sz[v]>sz[hso[u]]) hso[u]=v;
}
return ;
}
inline void dfs2(int u,int tp)
{
if(!u) return ;
p[u]=++cok;
fp[cok]=u;
top[u]=tp;
dfs2(hso[u],tp);
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa[u]||v==hso[u]) continue;
dfs2(v,v);
}
return ;
} inline void lca(int x,int y,int t)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
vec[p[top[x]]].push_back(make_pair(t,p[x]));
x=fa[top[x]];
}
if(deep[x]<deep[y]) swap(x,y);
vec[p[y]+1].push_back(make_pair(t,p[x]));
return ;
} int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
{
int x,y,op;
x=read(),y=read(),op=read();
if(op) add(x,y,i),add(y,x,i);
else
{
cnt++;
ed[cnt].u=x;
ed[cnt].v=y;
ed[cnt].id=i;
}
} deep[1]=1;
dfs1(1);
dfs2(1,1); for(int i=1;i<=cnt;i++)
lca(ed[i].u,ed[i].v,ed[i].id); priority_queue< pair<int,int> ,vector< pair<int,int> > , greater< pair<int,int> > >tq;
for(int i=1;i<=n;i++)
{
for(int j=0;j<vec[i].size();j++)
{
if(!tq.empty())
{
if(tq.top().first<vec[i][j].first&&tq.top().second>=vec[i][j].second) continue;
}
tq.push(vec[i][j]);
}
if(tq.empty())
{
dq[++cdq]=make_pair(cis[fp[i]],cis[fp[i]]);
}
else
{
while(!tq.empty())
{
if(tq.top().second<i) tq.pop();
else break;
}
if(tq.empty()) dq[++cdq]=make_pair(cis[fp[i]],cis[fp[i]]);
else dq[++cdq]=make_pair(min(cis[fp[i]],tq.top().first),cis[fp[i]]);
}
}
for(int i=1;i<=cnt;i++) dq[++cdq]=make_pair(ed[i].id,m+1); sort(dq+1,dq+cdq+1);
for(int i=1;i<=cdq;i++)
{
if(dq[i].se==0) continue;
ct++;
int k=dq[i].se;
if(k==m+1) k=dq[i].fi;
ans[k]=ct;
}
for(int i=1;i<=m;i++) write(ans[i]),printf(" ");
}

NOIP2023模拟2联测23 T2 害怕的更多相关文章

  1. [NOIP2018模拟赛10.23]发呆报告

    闲扯 考场看了眼题目感觉很难,一个小时敲完了所有暴力...嗯然后就在那里发呆什么事也没做 T3考场上把数据结构想了个遍都不会完成1操作,现在看这种思路其实之前也接触过... 比较玄学的一件事情就是T1 ...

  2. [NOI.AC省选模拟赛3.23] 染色 [点分治+BFS序]

    题面 传送门 重要思想 真的是没想到,我很久以来一直以为总会有应用的$BFS$序,最终居然是以这种方式出现在题目中 笔记:$BFS$序可以用来处理限制点对距离的题目(综合点分树使用) 思路 本题中首先 ...

  3. [jzoj 6080] [GDOI2019模拟2019.3.23] IOer 解题报告 (数学构造)

    题目链接: https://jzoj.net/senior/#main/show/6080 题目: 题意: 给定$n,m,u,v$ 设$t_i=ui+v$ 求$\sum_{k_1+k_2+...+k_ ...

  4. Wannafly挑战赛23 T2游戏 SG函数

    哎,被卡科技了,想了三个小时,最后还是大佬给我说是\(SG\)函数. \(SG\)函数,用起来很简单,证明呢?(不可能的,这辈子都是不可能的) \(SG\)定理 游戏的\(SG\)函数就是各个子游戏的 ...

  5. [NOI.AC省选模拟赛3.23] 集合 [数学]

    题面 传送门 一句话题意: 给定$n\leq 1e9,k\leq 1e7,T\leq 1e9$ 设全集$U=\lbrace 1,2,3,...n\rbrace $,求$(min_{x\in S}\lb ...

  6. Qbxt 模拟题 day2(am) T2 jian

    [问题描述] 有N个数,随机选择一段区间,如果这段区间的所有数的平均值在[L,R]中则你比较厉害.求你比较厉害的概率. [输入格式] 第一行有三个数N, l, r,含义如上描述. 接下来一行有N个数代 ...

  7. NOIP模拟赛(by hzwer) T2 小奇的序列

    [题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...

  8. 模拟赛DAY 2 T2不老梦

    [题目背景] 于万人中万幸得以相逢,刹那间澈净明通. 成为我所向披靡的勇气和惶恐,裂山海,堕苍穹. 爱若执炬迎风,炽烈而哀恸,诸般滋味皆在其中. 韶华宛转吟诵,苍凉的光荣,急景凋年深情难共. ——银临 ...

  9. 2.17NOIP模拟赛(by hzwer) T2 小奇的序列

    [题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...

  10. 【算法】dsu on tree初探

    dsu on tree的本质是树上的启发式合并,它利用启发式合并的思想,可以将O(N^2)的暴力优化成O(NlogN),用于不带修改的子树信息查询. 具体如何实现呢?对于一个节点,继承它重儿子的信息, ...

随机推荐

  1. 零基础学习人工智能—Python—Pytorch学习(八)

    前言 本文介绍卷积神经网络的上半部分. 其实,学习还是需要老师的,因为我自己写文章的时候,就会想当然,比如下面的滑动窗口,我就会想当然的认为所有人都能理解,而实际上,我们在学习的过程中之所以卡顿的点多 ...

  2. freertos学习笔记(十)事件标志组

    事件标志组 相当于用户平时定义的Flag,事件标志,不过freertos支持将该标志组作为启动task的条件 概述 分为8位和24位的模式(通过设置宏来配置) 每一位有0和1两个状态 用法 用于平常程 ...

  3. macOS 磁盘设备文件命名规则

    macOS 系统使用不同于 Linux 的磁盘设备命名规则.在 macOS 中,磁盘设备和分区被命名并通过 /dev 目录访问,类似于 Linux 和 UNIX 系统.但是,macOS的命名规则遵循特 ...

  4. 如何选择 Linux 发行版

    简介 要建立云服务器,首先需要安装操作系统.在现代环境中,几乎所有情况下都是指 Linux 操作系统.从历史上看,Windows 服务器和其他类型的 Unix 在特定的商业环境中都很流行,但现在几乎每 ...

  5. docker高级篇1-dockeran安装mysql主从复制

    大家好,咱们前面通过十篇的文章介绍了docker的基础篇,从本篇开始,咱们的<docker学习系列>将要进入到高级篇阶段(基础篇大家可以查看之前发布的文章). 咱们先来介绍:docker复 ...

  6. Android Camera2Video整合到自己项目里

    背景: Android项目里调用摄像头拍摄视频,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后来因项目需要,改成了camera2 1.Camera2Video 官方d ...

  7. seata 下载及安装

    分布式事务 参考文章: 分布式事务实战方案汇总 https://www.cnblogs.com/yizhiamumu/p/16625677.html 分布式事务原理及解决方案案例https://www ...

  8. mysql事务隔离级别及MVCC 原理

    一.事务的隔离级别 为了保证事务与事务之间的修改操作不会互相影响,innodb希望不同的事务是隔离的执行的,互不干扰. 两个并发的事务在执行过程中有 读读.读写(一个事务在读某条数据的同时另一个事务在 ...

  9. Kubelet证书自动续签(为 kubelet 配置证书轮换)

    1.概述 Kubelet 使用证书进行 Kubernetes API 的认证. 默认情况下,这些证书的签发期限为一年,所以不需要太频繁地进行更新. Kubernetes 包含特性 Kubelet 证书 ...

  10. Unity 配置 SQLite

    原Github仓库链接: https://github.com/robertohuertasm/SQLite4Unity3d?tab=readme-ov-file All you have to do ...