长跑

内存限制:128 MiB

时间限制:1000 ms

【题目描述】

某校开展了同学们喜闻乐见的阳光长跑活动。为了能“为祖国健康工作五十 年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加 3000 米长跑运 动。一时间操场上熙熙攘攘,摩肩接踵,盛况空前。 为了让同学们更好地监督自己,学校推行了刷卡机制。 学校中有 n 个地点,用 1 到 n 的整数表示,每个地点设有若干个刷卡机。 有以下三类事件: 1、修建了一条连接 A 地点和 B 地点的跑道。 2、A 点的刷卡机台数变为了 B。 3、进行了一次长跑。问一个同学从 A 出发,最后到达 B 最多可以刷卡多少 次。具体的要求如下: 当同学到达一个地点时,他可以在这里的每一台刷卡机上都刷卡。但每台刷 卡机只能刷卡一次,即使多次到达同一地点也不能多次刷卡。 为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向 单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从 A 地点 到 B 地点能刷卡的最多次数。

【输入描述】

输入的第一行包含两个正整数 n,m,表示地点的个数和操作的个数。 第二行包含 n 个非负整数,其中第 i 个数为第个地点最开始刷卡机的台数。 接下来有 m 行,每行包含三个非负整数 P,A,B,P 为事件类型,A,B 为事件 的两个参数。 最初所有地点之间都没有跑道。 每行相邻的两个数之间均用一个空格隔开。表示地点编号的数均在 1 到 n 之间,每个地点的刷卡机台数始终不超过 10000,P=1,2,3。

【输出描述】

输出的行数等于第 3 类事件的个数,每行表示一个第 3 类事件。如果该情况 下存在一种设定跑道方向的方案和路径的方案,可以到达,则输出最多可以刷卡 的次数。如果 A 不能到达 B,则输出-1。

输入样例:

9 31
10 20 30 40 50 60 70 80 90
3 1 2
1 1 3
1 1 2
1 8 9
1 2 4
1 2 5
1 4 6
1 4 7
3 1 8
3 8 8
1 8 9
3 8 8
3 7 5
3 7 3
1 4 1
3 7 5
3 7 3
1 5 7
3 6 5
3 3 6
1 2 4
1 5 5
3 3 6
2 8 180
3 8 8
2 9 190
3 9 9
2 5 150
3 3 6
2 1 210
3 3 6

输出样例:

-1
-1
80
170
180
170
190
170
250
280
280
270
370
380
580

题解

感觉好LCT啊。。。

先考虑一个简单的问题:

如何在一个支持加边的图中维护两点的连通性?

这不无脑并查集吗。。。

再考虑一个‘简单’的问题:

如何在一个支持加边的图中维护两点是否在同一个边双连通分量?

似乎不会。。。

发现形成的第一个边双连通分量一定是一个环

想了一下,发现可以用LCT+两个并查集

先用一个并查集check来维护连通性

再用一个并查集real来维护边双连通分量的集合

当我们加上一条边(u,v)时:

如果u,v不连通,就把它们在check上合并

如果u,v连通但不在一个边双连通分量,就把它们在LCT上的路径spilt出来,把路径上的点一个一个在real上合并

感觉会T,于是我们缩一下点,把已经合并了real的点从LCT中删掉,只保留它们的祖宗,祖宗要统计它们的所有信息

如果u,v在同一个边双连通分量里,就不管了

让我们回到这个题,我们任务的就是求两点路径的点权和+两点路径上的边双连通分量总点权和

我们就可以用上面的思路来维护边双连通分量的点权和

于是我们维护的就是一个由边双连通分量祖先构成的LCT

如图:

如果在已删除节点之间连边,就会使两个边双祖先合并,就会删掉其中之一

所以不同祖先的已删除节点都无连边。

代码实现还有许多细节:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100005
int n,m,val[N],a[N];//a是实际点权,val是祖先点权
struct node{int f[N];void init(){for(int i=1;i<=n;++i)f[i]=i;}int find(int x){return x==f[x]?x:f[x]=find(f[x]);}void uni(int x,int y){f[find(x)]=find(y);}
}real,check;
int fa[N],ch[N][2],sum[N];
bool rev[N];
inline bool pdc(int x){return ch[fa[x]][1]==x;}
inline bool pdr(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void pushdown(int x)
{if(rev[x]){swap(ch[x][0],ch[x][1]);if(ch[x][0])rev[ch[x][0]]^=1;if(ch[x][1])rev[ch[x][1]]^=1;rev[x]=0;}
}
void update(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];}
inline void rot(int x)
{int y=fa[x],z=fa[y];bool flg=pdc(x);if(!pdr(y)) ch[z][pdc(y)]=x;if(ch[y][flg]=ch[x][flg^1])fa[ch[y][flg]]=y;ch[x][flg^1]=y;fa[y]=x;fa[x]=z;update(y);update(x);
}
void pdpath(int x){if(!pdr(x)) pdpath(fa[x]);pushdown(x);}
inline void splay(int x)
{for(pdpath(x);!pdr(x);rot(x))if(!pdr(fa[x]))rot(pdc(fa[x])==pdc(x)?fa[x]:x);
}
inline void Access(int x)
{for(int last=0;x;last=x,x=fa[x]=real.find(fa[x])){//边Access边路径压缩找祖先,因为有可能遇到已删除的节点splay(x);ch[x][1]=last;update(x);}
}
inline void beroot(int x){Access(x);splay(x);rev[x]^=1;}
inline void link(int x,int y){beroot(x);fa[x]=y;}
void dfs(int &u,int d)//dfs只找LCT上的节点(即未删除节点)
{if(!u) return;real.uni(u,d);val[d]+=val[u];//把所有点权都统计加边双祖先上dfs(ch[u][0],d);dfs(ch[u][1],d);u=0;//删掉节点
}
int main()
{int i,op,u,v,d;scanf("%d%d",&n,&m);for(i=1;i<=n;i++)scanf("%d",&a[i]);for(i=1;i<=n;i++)val[i]=a[i];real.init();check.init();for(i=1;i<=m;i++){scanf("%d%d%d",&op,&u,&v);if(op==1){u=real.find(u);v=real.find(v);if(u==v) continue;if(check.find(u)!=check.find(v)){link(u,v);check.uni(u,v);}else{beroot(u);Access(v);splay(v);//把路径spilt出来dfs(ch[v][0],v);update(v);}}else if(op==2){d=real.find(u);splay(d);val[d]+=v-a[u];a[u]=v;update(d);}else{if(check.find(u)!=check.find(v)){printf("-1\n");continue;}u=real.find(u);v=real.find(v);beroot(u);Access(v);splay(v);printf("%d\n",sum[ch[v][0]]+val[v]);}}
}

好久都没写LCT了。。。

NOIP模拟赛8.16 C、长跑(LCT)相关推荐

  1. 【noip模拟赛4】Matrix67的派对 暴力dfs

    [noip模拟赛4]Matrix67的派对 描述 Matrix67发现身高接近的人似乎更合得来.Matrix67举办的派对共有N(1<=N<=10)个人参加,Matrix67需要把他们安排 ...

  2. 辣鸡(ljh) NOIP模拟赛 模拟 平面几何 数论 化学相关(雾)

    [题目描述] 辣鸡ljhNOI之后就退役了,然后就滚去学文化课了. 然而在上化学课的时候,数学和化学都不好的ljh却被一道简单题难住了,受到了大佬的嘲笑. 题目描述是这样的:在一个二维平面上有一层水分 ...

  3. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  4. 【HHHOJ】NOIP模拟赛 捌 解题报告

    点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...

  5. jyzy noip模拟赛5.22-2

    不知道哪来的题 jyzy noip模拟赛5.22-2 样例输入 1 2 3 4 样例输出 0.200000000000000 数据 |a|,|b|,|c|,|d|<=1e9 很多大佬迅速想到二分 ...

  6. NOIP模拟赛csy2021/10/30

    NOIP模拟赛csy2021/10/30 比赛时间规划 赛后反思与总结 这..总的来说感觉打的很不好,根本没有状态,有一部分原因是今天来晚了,太慌,更多的还是这次题感觉很难o(╥﹏╥)o 比赛时间规划 ...

  7. 【WZOI第二次NOIP模拟赛Day1T2】世界末日 解题报告

    [WZOI第二次NOIP模拟赛Day1T2]世界末日 Problem 2 世界末日 (doomsday.pas/c/cpp) 背景 话说CWQ大牛终于打开了那扇神秘大门,但迎接他的不是什么神秘的东西, ...

  8. NOIP 模拟赛 长寿花 题解

    NOIP 模拟赛 长寿花 题解 要放 \(n\) 层物品,第 \(i\) 层有 \(a_i\) 个位置放物品,物品有 \(m\) 中颜色,有约束条件: 同一层两个相邻物品颜色不能相同. 相邻两层颜色集 ...

  9. NOIP模拟赛 17.10.10

    初次见面(firstmeet) [题目背景] 雾之湖边,静得可怕. 露米娅出神凝望.黑白连衣裙,像极了绽放的墨黑和洁白的莲.身边的雾之 湖,倒映着血色天空.酒红的双眸,映照一切.低声浅笑,双臂伸直,她 ...

最新文章

  1. 注册ETM钱包瓜分糖果 更有机会独享8888元现金奖励
  2. hdu 4640(状压dp)
  3. Spring Boot (七)MyBatis代码自动生成和辅助插件
  4. Flutter入门:dart基础
  5. css3 的 calc()函数在布局中的使用----头部高度固定,页面正好占满一屏
  6. java --replaceAll方法
  7. php 跳回上一页_php – Laravel 5 – 登录后重定向回到上一页
  8. 程序员应该如何提问?
  9. html如何设置轮动,手把手教你构建轮动策略
  10. springmvc 带查询条件的分页,form的控制范围,怎么包裹条件提交给后台
  11. oracle das系统,分布式声波传感系统DAS
  12. 与MyBatis的第一次见面课
  13. 学术族谱典型用户及典型场景模拟
  14. Rust: 外部函数接口(FFI)
  15. 软件架构--工业软件架构分析
  16. 五十个产品可靠性性能提高的方法详解
  17. 【SVG】svg入门
  18. 小程序开发合同_小程序开发公司在哪里找?
  19. NFT自由人数字艺术藏品有收藏价值吗?
  20. 机器学习(一)——随机游走

热门文章

  1. 怎样在计算机上设置纸大小,打印机怎么设置纸张大小 打印机设置打印纸张大小的步骤教程...
  2. mysql 索引 二_MySql索引(二)
  3. 西安电子科技大学计算机类考研数据速览
  4. 【Lingo】分段函数
  5. Spring Boot 从入门到精通(一)HelloWorld(构建项目,热部署,测试)
  6. 四川泸州市高职计算机学校,四川泸州职高学校有哪些?
  7. Chrome Extension 介绍
  8. 毛桃pe系统 linux,老毛桃U盘PE重装教程
  9. 我de虚拟经济学系列---第二章 经济繁荣不建桥
  10. 完美修改证件照背景详细步骤,可以消除边界处的白边或者红边