NOIP2023模拟2联测23 T2 害怕
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 害怕的更多相关文章
- [NOIP2018模拟赛10.23]发呆报告
闲扯 考场看了眼题目感觉很难,一个小时敲完了所有暴力...嗯然后就在那里发呆什么事也没做 T3考场上把数据结构想了个遍都不会完成1操作,现在看这种思路其实之前也接触过... 比较玄学的一件事情就是T1 ...
- [NOI.AC省选模拟赛3.23] 染色 [点分治+BFS序]
题面 传送门 重要思想 真的是没想到,我很久以来一直以为总会有应用的$BFS$序,最终居然是以这种方式出现在题目中 笔记:$BFS$序可以用来处理限制点对距离的题目(综合点分树使用) 思路 本题中首先 ...
- [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_ ...
- Wannafly挑战赛23 T2游戏 SG函数
哎,被卡科技了,想了三个小时,最后还是大佬给我说是\(SG\)函数. \(SG\)函数,用起来很简单,证明呢?(不可能的,这辈子都是不可能的) \(SG\)定理 游戏的\(SG\)函数就是各个子游戏的 ...
- [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 ...
- Qbxt 模拟题 day2(am) T2 jian
[问题描述] 有N个数,随机选择一段区间,如果这段区间的所有数的平均值在[L,R]中则你比较厉害.求你比较厉害的概率. [输入格式] 第一行有三个数N, l, r,含义如上描述. 接下来一行有N个数代 ...
- NOIP模拟赛(by hzwer) T2 小奇的序列
[题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...
- 模拟赛DAY 2 T2不老梦
[题目背景] 于万人中万幸得以相逢,刹那间澈净明通. 成为我所向披靡的勇气和惶恐,裂山海,堕苍穹. 爱若执炬迎风,炽烈而哀恸,诸般滋味皆在其中. 韶华宛转吟诵,苍凉的光荣,急景凋年深情难共. ——银临 ...
- 2.17NOIP模拟赛(by hzwer) T2 小奇的序列
[题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...
- 【算法】dsu on tree初探
dsu on tree的本质是树上的启发式合并,它利用启发式合并的思想,可以将O(N^2)的暴力优化成O(NlogN),用于不带修改的子树信息查询. 具体如何实现呢?对于一个节点,继承它重儿子的信息, ...
随机推荐
- 传染病模型 SI
参考了这篇写的很好的[1],讲了各种模型 因为是各种模型都是用微分方程写的,所以又去学习了一下微分方程 ,真的忘了有没有学过这个,反正一点印象也没有了. 好在[2] 这个文章又把我带回去了. SI 的 ...
- TypeScript 5.1 & 5.2
getter 和 setter 可以完全不同类型了 以前我们提过,getter 的类型至少要是其中一个 setter 的类型.这个限制被突破了.现在可以完全使用不同类型了. v5.1 后,没有再报错了 ...
- Angular 18+ 高级教程 – Signals
前言 首先,我必须先说明清楚.Signal 目前不是 Angular 的必备知识. 你的项目不使用 Signal 也不会少了条腿,断了胳膊. Angular 官方维护的 UI 组件库 Angular ...
- TypeScript – Decorator 装饰器
前言 TypeScript 5.0 之后就可以使用正真的 JS Decorator 了, 从前 experiment 的版本依然可用, 但是不建议继续用, 因为差很远, 一起用会混乱. Decorat ...
- LLM应用实战: 文档问答系统Kotaemon-1. 简介及部署实践
1.背景 本qiang~这两周关注到一个很火的开源文档问答系统Kotaemon,从8月28日至今短短两周时间,github星标迅猛增长10K,因此计划深挖一下其中的原理及奥秘. 本篇主要是Kotaem ...
- 多表查询 —— 内连接&外连接&子查询
连接查询 内连接 1.查询语法 -- 隐式内连接 select 字段列表 from 表1, 表2... where 条件; -- 显式内连接 select 字段列表 from 表1 [INNER] j ...
- 数字产品护照 (DPP) 解决方案:利用 Blazor 和区块链实现产品全生命周期追踪
数字产品护照 (DPP) 解决方案:利用 Blazor 和区块链实现产品全生命周期追踪 随着全球对可持续发展和产品透明度的关注日益增加,企业需要一种可靠的方法来跟踪和管理产品生命周期中的关键数据.我们 ...
- Qt表格入门
摘要 表格作为数据展示的界面,会在很多场景下使用.Qt为我们提供了使用简单方便和扩展性强的表格视图,这里做一个简单的入门整理. 个人能力有限,有错误欢迎留言指正,如果你有更好的方法,也 ...
- [29] CSP模拟2
A.不相邻集合 考虑值域上连续的段,可以发现连续的长度为 \(x\) 的段的贡献必定为 \(\lceil{\frac{x}{2}}\rceil\) 考虑并查集维护值域连续的段的大小,每次询问求出全部连 ...
- 第22天:安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用
#数据库操作-mysqli函数&增删改查 PHP函数:连接,选择,执行,结果,关闭等 参考:https://www.runoob.com/php/php-ref-mysqli.html 常用: ...