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. 带你了解 WebAssembly 的发展、应用与开发

    一.WebAssembly 是什么? "WebAssembly(缩写为 Wasm)是一种基于堆栈式虚拟机的二进制指令集.Wasm 被设计成为一种编程语言的可移植编译目标,并且可以通过将其部署 ...

  2. C# 使用正则表达式 将金额转换为中文大写

    /// <summary> /// decimal转换成中文大写 /// </summary> /// <param name="number"> ...

  3. iptables 命令使用帮助总结

    本文为博主原创,转载请注明出处: 1.iptables 命令帮助参数 root@controller1:~# iptables --help iptables v1.6.1 Usage: iptabl ...

  4. ansible部署jdk source /etc/profile 不起作用?

    问题: ansible调用playbook远程mvn执行打包时发现执行出错,找不到JAVA_HOME.我们的exporter JAVA_HOME=/usr/java/jdk1.8.0写在/etc/pr ...

  5. c++ 命名的强制类型转换

    显式转换:显式将一种类型转换为另一种类型. References: C++中的显示数据类型转换 与命名的强制类型转换相比,旧式的强制类型转换从表现形式上来说不那么清晰明了,容易被看漏,所以一旦转换过程 ...

  6. Angular 学习笔记 (Angular 12 get started)

    Angular 12 视乎比以往更稳定了. 这里记入一般的 get started 结构和做法. 第 1 步, 创建项目. ng new project --create-application=fa ...

  7. face-api.js 学习笔记

    参考 Build Real Time Face Detection With JavaScript (youtube get started) face-api.js - JavaScript API ...

  8. EditPlus各个版本的注册码,可用

    原文链接:https://www.cnblogs.com/shihaiming/p/6422441.html 工具: editplus注册码生成链接: http://www.jb51.net/tool ...

  9. MyBatis——解决SQL映射文件的警告提示

    解决SQL映射文件的警告提示 产生原因:idea 和数据库没有建立连接,不识别表信息 解决方式:在idea 中配置MySQL数据库连接   配置MySQL数据库连接:                  ...

  10. 递归获取zip中的文件

    1 //tempPath 系统临时文件夹 2 2 private List<String> getWsContentList(String tempPath) { 3 3 //wsFile ...