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

Input

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

Output

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

Sample Input

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

Sample Output

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

Hint

数据规模及约定

  对于100%的数据,m<=5n,任意时刻,每个地点的刷卡机台数不超过10000。N<=1.5×105

分析:只有加边没有删边操作,我们考虑把每次把新形成的边双缩成一个点,这样每次询问就相当于查询当前缩点后树上的权值和了,每次缩点用并查集暴力合并就好。

#include <bits/stdc++.h>
#define INF 2147483640
#define eps 1e-9
const int MAXN = 1e6 + 5;
using namespace std;
int n,m,q,f[MAXN],f2[MAXN],s[MAXN],ch[MAXN][2],val[MAXN],sum[MAXN],fa[MAXN];
bool lazy[MAXN];
inline int nextChr()
{static const int siz=1<<22;static char buf[siz],*chr=buf+siz;if(chr==buf+siz)fread(chr=buf,1,siz,stdin);return int(*chr++);
}
inline int read()
{register int r=0,c=nextChr();for(;c<48;c=nextChr());for(;c>47;c=nextChr())r=(r<<3)+(r<<1)+c-48;return r;
}
inline int Find(int x)
{if(f[x] == x) return x;f[x] = Find(f[x]);return f[x];
}
inline int Find2(int x)
{if(f2[x] == x) return x;f2[x] = Find2(f2[x]);return f2[x];
}
inline bool isroot(int x)
{return ch[Find(fa[x])][0] != x && ch[f[fa[x]]][1] != x;
}
void push_up(int x)
{int ls = ch[x][0],rs = ch[x][1];sum[x] = sum[ls] + sum[rs] + val[x];
}
void rotate(int x)
{int y = Find(fa[x]),z = Find(fa[y]);int d = ch[y][0] == x ? 0 : 1;if(!isroot(y)){if(ch[z][0] == y) ch[z][0] = x;else ch[z][1] = x;}fa[y] = x,fa[x] = z;fa[ch[x][d^1]] = y;ch[y][d] = ch[x][d^1],ch[x][d^1] = y;push_up(y),push_up(x);
}
inline void push_down(int x)
{if(!lazy[x]) return;int ls = ch[x][0],rs = ch[x][1];lazy[x] ^= 1;lazy[ls] ^= 1;lazy[rs] ^= 1;swap(ch[ls][0],ch[ls][1]);swap(ch[rs][0],ch[rs][1]);
}
void splay(int x)
{int tot = 0;s[++tot] = x;for(int i = x;!isroot(i);i = fa[i]) s[++tot] = fa[i];for(;tot;tot--) push_down(s[tot]);while(!isroot(x)){int y = fa[x],z = Find(fa[y]);if(!isroot(y)){if((ch[z][0] == y) ^ (ch[y][0] == x)) rotate(x);else rotate(y);}rotate(x);}
}
void access(int x)
{int t = 0;while(x){splay(x);ch[x][1] = t;push_up(x);t = x,x = Find(fa[x]);}
}
void makeroot(int x)
{access(x),splay(x);swap(ch[x][0],ch[x][1]);lazy[x] ^= 1;
}
void link(int x,int y)
{makeroot(x);fa[x] = y;f2[f2[x]] = y;
}
bool linked(int x,int y)
{return Find2(x) == Find2(y);
}
void rebuild(int x,int y)
{if(!x) return;f[f[x]] = y;rebuild(ch[x][0],y);rebuild(ch[x][1],y);
}
int main()
{n = read(),m = read();for(int i = 1;i <= n;i++){val[i] = read();sum[i] = val[i];}for(int i = 1;i <= 2*n;i++) f[i] = f2[i] = i;for(int i = 1;i <= m;i++){int p,x,y;p = read(),x = read(),y = read();if(p == 1){if(!linked(Find(x),Find(y))) link(f[x],f[y]);else {makeroot(f[x]);access(f[y]);splay(f[y]);++n;val[n] = sum[n] = sum[f[y]];f2[n] = f2[f[y]];rebuild(f[y],n);}}if(p == 2){makeroot(Find(x));access(f[x]);splay(f[x]);sum[f[x]] += y-val[x];val[f[x]] += y-val[x];val[x] = y;}if(p == 3){if(!linked(Find(x),Find(y))) printf("-1\n");else {makeroot(f[x]);access(f[y]);splay(f[y]);printf("%d\n",sum[f[y]]);}}}
}

HYSBZ - 2959 长跑(动态树+并查集)相关推荐

  1. bzoj 2959: 长跑(LCT+并查集)

    2959: 长跑 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 315  Solved: 178 [Submit][Status][Discuss] ...

  2. BZOJ 2959 长跑 (LCT、并查集)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2959 题解 真是被这题搞得心态大崩--调了7个小时--然而并查集都能写成\(O(n^2) ...

  3. HDU 1512 Monkey King 左偏树 + 并查集

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1512 题意:有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害. ...

  4. 可持久化线段树【主席树】可持久化并查集【主席树+并查集】

    笼统的主席树原理 众所周知, 主席树是可以持久化的, 换言之你能知道你所维护信息的所有历史状态. 主席树是这样做的: 1. 首先建一颗朴素的线段树,代表初始状态 (下图黑色) , 也就是第0次操作后的 ...

  5. POJ - 2513 Colored Sticks(字典树+并查集+欧拉回路)

    题目链接:点击查看 题目大意:给出n个木棍,问若两两相连,最终能否构成一根长直木棍,相连的规则是两个木棍的相接端点的颜色需要保持相同 题目分析:关于这个题目,我们可以将每个木棍视为一条边,每个木棍的两 ...

  6. HDU2545 树上战争【树+并查集】

    树上战争 Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  7. 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]

    Vladik and Entertaining Flags Time Limit: 20 Sec  Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...

  8. HDU 1512 Monkey King(左偏树+并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1512 题       意: 有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示 ...

  9. UVA 1455 Kingdom 线段树+并查集

    并查集维护:y的最大最小值.城市数量 线段树维护:城市数量,洲数量 合并两个集合时,先在线段树上删除两个子集合的旧的信息,然后再将合并完的新集合更新到线段树. //#pragma comment(li ...

最新文章

  1. Ajax弹出式无刷新城市选择特效
  2. How to use xxnet for linux
  3. Windows server 2008 iis7/iis7.5启用父路径的方法
  4. antd 上传进度_antd vue upload组件使用customRequest上传文件显示文件上传进度
  5. 算法学习笔记(一):二分法及其实现
  6. Scala 中将方法、函数、函数式编程和面向对象编程关系分析图
  7. PHP 5.3以上版本新增的一些方法
  8. 揭秘MySQL生态重要功能,X-Engine引擎核心能力——OnlineDDL
  9. 不染用计算机数字,2013年计算机等级考试一级B知识预测题(6)
  10. 300字简单区分线程问题
  11. php打印机 纸张大小,打印设置信息中的纸张类型,如何取自定义纸张!
  12. 解决vscode中getch()函数报错。C语言。getch()的头文件。
  13. 不再恐惧入侵者 DLL后门完全清除方法(转)
  14. tar命令的讲解与使用
  15. 用python来更改小伙伴的windows开机密码,不给10块不给开机
  16. Adobe illustrator(AI) 矢量图形软件 | 图像描摹(怎么把白色背景色的图片背景变为透明色)
  17. Python检测重复字——部分中华字经重复字检测
  18. 使用键盘设置桌面计算机图标的显示不出来,显示桌面,小编教你显示桌面图标不见了如何恢复...
  19. 安卓源码目录最全解析
  20. 实现智能dns为用户分配最佳线路

热门文章

  1. 两个苹果手机怎么定位_苹果6手机一直闪白屏怎么办?苹果6手机一直闪白屏怎么办?...
  2. C# 处理PPT水印(二)——去除水印效果(文本水印、图片水印)
  3. java foreach 空指针_foreach循环报NPE空指针异常
  4. 相关性分析热点图_防老剂TMQ及6PPD价格上涨逻辑分析及后市展望
  5. saas(sccs)、less、stylus三者的区别
  6. Secret Layer Ligh(数据加密成图片)v2.7.2绿色版
  7. WebSocket无法连接问题
  8. 微信隐藏/显示右上角菜单接口
  9. 与技术无关,但却值得码农们好好读一读的怪书:禅与摩托车维修艺术
  10. P1039 侦探推理