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. Mac 删除 Steam 游戏图标

    Steam 将游戏安装在了 ~/Applications,打开访达,前往该目录,将相关游戏移到废纸篓.

  2. LaTeX hyperref 包去掉链接方框

    \usepackage[hidelinks]{hyperref}

  3. Redis实战9-全局唯一ID

    发布优惠券的时候,每个店铺都可以发布优惠券,当用户抢购的时候,优惠券表中的id如果使用数据库的自增长ID会存在以下问题: 1:id的规律太明显,容易被刷 2:当数据量很大的时候,会受到单表数据的限制 ...

  4. 【YashanDB数据库】Ubuntu系统加载Yashan C驱动后无法使用PHP

    [问题分类]驱动使用 [关键字]驱动使用.PHP.Ubuntu.C驱动 [问题描述] 客户将YashanDB的C驱动lib加载到环境变量LD_LIBRARY_PATH后,PHP报错:PHP Fatal ...

  5. LLog:Spring轻量级请求日志监控组件,集成管理面板,支持多条件查询检索

    开源地址 https://gitee.com/lboot/LLog 简介 LLog是基于AOP构建的请求日志记录和查询工具库,通过引入该工具库,完成配置,实现对接口请求日志的记录.查询检索等功能. 请 ...

  6. 闲的蛋疼整理了一下Dockerfile的命令和参数备查

    Dockerfile 主要指令及参数: 指令 主要参数 作用 用法示例 FROM <image>[:<tag>] [AS <name>] 指定基础镜像 FROM u ...

  7. ASP.NET Core Library – Google libphonenumber (Country Dial Code)

    前言 Google libphonenumber 是 Java 的, ASP.NET Core 只是 port 过去而已. 以前在 angular2 学习笔记 ( translate, i18n 翻译 ...

  8. ASP.NET Core Library – MailKit SMTP Client

    前言 以前写的 SMTP Client 相关文章: Asp.net core 学习笔记 ( Smtp and Razor template 电子邮件和 Razor 模板 ) ASP.NET Email ...

  9. QT数据可视化框架编程实战之三维柱状图_补天云QT技术培训专家

    QT数据可视化框架编程实战之三维柱状图_补天云QT技术培训专家 文章目录 QT数据可视化框架编程实战:三维柱状图可视化运行效果 主程序实现C++代码 主场景 QML代码 坐标轴QML代码 数据模型定义 ...

  10. 线段树 transformation——hdu 4578

    问题描述: 给定一个数列,数列中所有元素都初始化为0,对其执行多种区间操作 操作1:add修改:对区间[L,R]内的所有数加c 操作2:multi修改:对区间[L,R]内所有数乘以c 操作3:chan ...