正题

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


题目大意

\(n\)个点有权值,要求支持操作

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

解题思路

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

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

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

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

时间复杂度\(O(n\log n)\)


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. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  2. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

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

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

  4. P3273 [SCOI2011]棘手的操作

    吐槽 上午风浔凌julao问我的神题 操作又多又毒瘤又棘手... 然后bzoj题号正好是2333,2333333333 思路 貌似只有我是这么写的 线段树合并, 每个线段树存每个连通块的信息,维护点的 ...

  5. 洛谷P3273 [SCOI2011]棘手的操作

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

  6. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  7. ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集

    正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法. 首先题意是给出n个点,m次操作. 操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块. 最少的求法 ...

  8. 【BZOJ 4662】 4662: Snow (线段树+并查集)

    4662: Snow Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 136  Solved: 47 Description 2333年的某一天,临冬突 ...

  9. [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]

    题面 一句话题意: 给定一张 N 个点, M 条边的无向连通图, 每条边上有边权 w . 求删去任意一个点后的最小生成树的边权之和. 思路 首先肯定要$kruskal$一下 考虑$MST$里面去掉一个 ...

随机推荐

  1. WPF 饼状图,柱形图,折线图 (1 柱形图)

    WPF三贱客绘制,柱形图应该是比较简单的一个了.效果如下: ItemSource数据结构可自己定义,我的如下列子,自定义的数据结构属性,要对应配置下DisplayMemberMsg 和DisplayM ...

  2. WPF---数据模板(一)

    一.场景模拟 假设我们现在有如下需求: 我们需要在ListBox中的每个Item中显示某个成员的姓名.年龄以及喜欢的颜色,点击Item的时候,会在右边显示详细信息,同时也想让ListBox的样式变得好 ...

  3. QT 中的模态和非模态对话框

    void MainWindow::on_pushButton_clicked() { //模态 QDialog dlg(this); dlg.resize(100,100); dlg.exec(); ...

  4. Thread类的常用方法----多线程基础练习

    创建多线程程序的第一种方式----继承Thread类 常用API 构造方法 public Thread() :分配一个新的线程对象. public Thread(String name) :分配一个指 ...

  5. 使用servlet中是否需要考虑线程问题

    package day09; import java.io.IOException; import javax.servlet.ServletException; import javax.servl ...

  6. 【CSS复合选择器、元素显示模式、背景】前端小抄(3) - Pink老师自学笔记

    [CSS复合选择器.元素显示模式.背景]前端小抄(3) 本学习笔记是个人对 Pink 老师课程的总结归纳,转载请注明出处! 一.CSS的复合选择器 1.1 什么是复合选择器 在 CSS 中,可以根据选 ...

  7. LeetCode入门指南 之 动态规划思想

    推荐学习labuladong大佬的动态规划系列文章:先弄明白什么是动态规划即可,不必一次看完.接着尝试自己做,没有思路了再回过头看相应的文章. 动态规划一般可以由 递归 + 备忘录 一步步转换而来,不 ...

  8. 太空大战-GUI实现(1)

    1.复习GUI后,第一天实现的效果 2. 项目实现思路 基本的窗口界面实现就不讲了,源码都看得懂的,这里只说其中比较重要的几个功能的实现. 面板的绘制(所有图形的绘制) 首先,需要在GamePanel ...

  9. spring boot 系列之七:SpringBoot整合Mybatis

    springboot已经很流行,但是它仍需要搭配一款ORM框架来实现数据的CRUD,之前已经分享过JdbcTemplete和JPA的整合,本次分享下Mybatis的整合. 对于mybatis的使用,需 ...

  10. You-Get开源在线下载神器,搭配python更加丝滑(文中案例演示)

    大家好,我是辰哥 今天给大家介绍一个号称可以下载全网视频.音频.图像的开源库 --you-get you-get 这里说全网可能一点夸张,但如果实际上去使用you-get下载媒体文件(视频.音频.图像 ...