正题

题目链接:https://www.luogu.com.cn/problem/P3273


题目大意

nnn个点有权值,要求支持操作

  1. 连接两个点
  2. 单点加权
  3. 联通块加权
  4. 全图加权
  5. 单点询问
  6. 联通块询问最大值
  7. 全图询问最大值

解题思路

把所有可能产生的联通块都变到一个区间里就好了

考虑怎么排这个东西,可以先离线,每次加边的时候连接两个联通块根,这样跑出来的dfsdfsdfs序就是符合要求的。

注意因为邻接表是按照加边的顺序倒着枚举的,所以要反过来加边。

然后用线段树直接维护答案就好了

时间复杂度O(nlog⁡n)O(n\log n)O(nlogn)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+10;
struct qnode{char op[3];int x,y;
}p[N];
struct node{int to,next;
}a[N];
int n,q,tot,cnt,ls[N],w[N],fa[N],l[N],r[N];
struct SegTree{int w[N<<2],lazy[N<<2];void Downdata(int x){if(!lazy[x])return;w[x*2]+=lazy[x];lazy[x*2]+=lazy[x];w[x*2+1]+=lazy[x];lazy[x*2+1]+=lazy[x];lazy[x]=0;return;}void Change(int x,int L,int R,int l,int r,int val){if(L==l&&R==r){w[x]+=val;lazy[x]+=val;return;}int mid=(L+R)>>1;Downdata(x);if(r<=mid)Change(x*2,L,mid,l,r,val);else if(l>mid)Change(x*2+1,mid+1,R,l,r,val);else Change(x*2,L,mid,l,mid,val),Change(x*2+1,mid+1,R,mid+1,r,val);w[x]=max(w[x*2],w[x*2+1]);return;}int Ask(int x,int L,int R,int l,int r){if(L==l&&R==r){return w[x];}int mid=(L+R)>>1;Downdata(x);if(r<=mid)return Ask(x*2,L,mid,l,r);if(l>mid)return Ask(x*2+1,mid+1,R,l,r);return max(Ask(x*2,L,mid,l,mid),Ask(x*2+1,mid+1,R,mid+1,r));}
}T;
void addl(int x,int y){if(x==y)return;a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
int find(int x)
{return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
void dfs(int x){l[x]=r[x]=++cnt;T.Change(1,1,n,cnt,cnt,w[x]);for(int i=ls[x];i;i=a[i].next)dfs(a[i].to);return;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&w[i]),fa[i]=i;scanf("%d",&q);for(int i=1;i<=q;i++){scanf("%s",p[i].op);if(p[i].op[0]=='U'){scanf("%d%d",&p[i].x,&p[i].y);p[i].x=find(p[i].x);p[i].y=find(p[i].y);if(p[i].x==p[i].y)continue;if(p[i].x<p[i].y)swap(p[i].x,p[i].y);fa[p[i].y]=p[i].x;}else if(p[i].op[0]=='A'&&p[i].op[1]=='1')scanf("%d%d",&p[i].x,&p[i].y);else if(p[i].op[0]=='A'&&p[i].op[1]=='2')scanf("%d%d",&p[i].x,&p[i].y);else if(p[i].op[0]!='F'||p[i].op[1]!='3')scanf("%d",&p[i].x);}for(int i=q;i>=1;i--)if(p[i].op[0]=='U')addl(p[i].x,p[i].y);for(int i=1;i<=n;i++)if(find(i)==i)dfs(i);for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=q;i++){int x=p[i].x,y=p[i].y;if(p[i].op[0]=='U'){if(x==y)continue;fa[y]=x;r[x]=r[y];}else if(p[i].op[0]=='A'&&p[i].op[1]=='1')T.Change(1,1,n,l[x],l[x],y);else if(p[i].op[0]=='A'&&p[i].op[1]=='2')x=find(x),T.Change(1,1,n,l[x],r[x],y);else if(p[i].op[0]=='A'&&p[i].op[1]=='3')T.Change(1,1,n,1,n,x);else if(p[i].op[0]=='F'&&p[i].op[1]=='1')printf("%d\n",T.Ask(1,1,n,l[x],l[x]));else if(p[i].op[0]=='F'&&p[i].op[1]=='2')x=find(x),printf("%d\n",T.Ask(1,1,n,l[x],r[x]));else printf("%d\n",T.Ask(1,1,n,1,n));}return 0;
}

P3273-[SCOI2011]棘手的操作【线段树,并查集】相关推荐

  1. bzoj2333: [SCOI2011]棘手的操作 线段树+离线

    网上都是可并堆在线搞,其实直接离线处理处每个联通块,然后把他们放一起,然后点更新,区间询问就可以了. #include <iostream> #include <algorithm& ...

  2. 洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]

    题目传送门 棘手的操作 题目描述 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 ...

  3. 【BZOJ5005】乒乓游戏 [线段树][并查集]

    乒乓游戏 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 5 1 1 5 1 5 11 2 ...

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

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

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

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

  6. bzoj 2054: 疯狂的馒头(线段树||并查集)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...

  7. P5631-最小mex生成树【线段树,并查集】

    正题 题目链接:https://www.luogu.com.cn/problem/P5631 题目大意 nnn个点mmm条边的一张图,求mexmexmex值最小的一棵生成树. 解题思路 考虑比较暴力的 ...

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

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

  9. hdu 1558(线段相交+并查集)

    题意:给你一些操作,P后边输入四个值,分别代表一条线段的起点.终点坐标,当输入Q时,后边输入一个整形值K,输出第k条线段所在的集合中包含的线段的个数. 解题思路:线段相交+并查集,sum[i]表示i所 ...

最新文章

  1. zepto打造一款移动端划屏插件
  2. 点云处理关键算法剖析及实现(涉及滤波、分割、配准、识别、重建)
  3. cstring 比较_属牛人和属蛇人姻缘婚配关系比较和谐
  4. ios推送服务,php服务端
  5. 跟着 Alex 学python 1.安装
  6. python面试题(4)--- 字符串首字母大小写 和 反转字符串 问题
  7. 伯克利、OpenAI等提出基于模型的元策略优化强化学习
  8. 安装git之后,桌面出现蓝色问号的解决方法
  9. html文档是哪个版本,Pro010-从零开始HTML[#010]——5分钟-HTML 文档类型版本
  10. linux修改主机名(不重启)
  11. 给定数组,查找最小的k个元素或最大的k个元素
  12. 五笔输入法的学习记录
  13. 04 - 雷达的工作频率
  14. 基于Matlab的人脸识别设计(PCA)
  15. linux给普通用户添加管理员权限,linux 赋予普通用户管理员权限
  16. 使用WebDriver 登录163邮箱
  17. 使用tornado如何实现请求异步非阻塞?
  18. java 多个线程同时写同一个文件
  19. rj45 千兆接口定义_RJ45接口针脚定义(各种接口针脚定义)
  20. 思博伦报告:伴随运营商寻求差异化优势,5G发展不断加速

热门文章

  1. android http 三次 握手,面试解析:3次握手与4次挥手
  2. 转换实体类_利用Java反射机制进行Map和JavaBean间转换
  3. U盘安装Linux挂载cd,U盘安装Ubuntu Server CD-ROM挂载失败
  4. yml php,使用 docker-compose.yml 快速搭建php开发环境
  5. python逐行读取数据时出现错误_python如何逐行读取数据
  6. endpointimpl怎么填参数_这是一篇VLOOKUP函数家族主要用法的合集,XLOOKUP来了!真香!但是,没有office365吃不着怎么办?...
  7. threejs 加载两个场景_threejs中的三维场景操作
  8. 线程与线程池(一条龙详解)
  9. 7-5 汽车加油问题 (20 分)(思路+详解)Come 宝!!!!!!!!!!!!!
  10. 广西高考成绩查询2021,2021年广西高考个人排名怎么查询,广西高考成绩排名查询方法...