http://www.lydsy.com/JudgeOnline/problem.php?id=2333 (题目链接)

题意

  N个节点维护一些操作。。

Solution

  我们用可并大根堆进行维护。

  对于每个连通块建一个局部可并堆,因为要询问全局最大值,所以还要对全局建一个全局可并堆记录之前局部可并堆堆顶元素。

  U:合并x所在的堆以及y所在的堆,并在全局堆中删除合并前的局部堆堆顶元素,因为它合并以后已经不是其连通块的堆顶了。

  A1:在堆中删除,更新后再加入堆

  A2:找到其堆顶,对堆顶进行修改并打上标记

  A3:对全局都打个标记即可

  F1:将标记下传后输出

  F2:找到其所在的堆顶输出

  F3:输出全局堆的堆顶

  

  UPD:这个做法被×了,暴力找堆顶复杂度不对,得写启发式合并或者线段树,右转LCF。。当然拿来练练手也是可以的,反正能过数据

细节

  码农题就是细节多

代码

// bzoj2333
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=300010;
struct heap {int val,tag,l,r,fa;}q[maxn],qq[maxn];
int n,m,rt,Tag;
char op[10]; void pushdown(heap *q,int k) { //标记下传
q[q[k].l].val+=q[k].tag;q[q[k].l].tag+=q[k].tag;
q[q[k].r].val+=q[k].tag;q[q[k].r].tag+=q[k].tag;
q[k].tag=0;
}
int merge(heap *q,int x,int y) { //合并
if (x==0 || y==0) return x+y;
if (q[x].val<q[y].val) swap(x,y);
if (q[x].tag) pushdown(q,x);
q[x].r=merge(q,q[x].r,y);
q[q[x].r].fa=x;
swap(q[x].l,q[x].r);
return x;
}
int find(heap *q,int x) { //寻找堆顶并下传标记,注意下传标记和向上查询的顺序
int tmp=x;
if (q[x].fa) tmp=find(q,q[x].fa);
if (q[x].tag) pushdown(q,x);
return tmp;
}
int del(heap *q,int x) { //删除
int f=find(q,x);
int tmp=merge(q,q[x].l,q[x].r);
if (q[q[x].fa].l==x) q[q[x].fa].l=tmp;
else q[q[x].fa].r=tmp;
q[tmp].fa=q[x].fa;
return f==x ? (tmp ? find(q,tmp) : 0) : f; //返回删除后该堆的堆顶,此处不是很好处理,最好画个图理解一下
}
int build() { //对全局建堆
queue<int> Q;
for (int i=1;i<=n;i++) Q.push(i),qq[i]=q[i];
while (Q.size()>1) {
int x=Q.front();Q.pop();
int y=Q.front();Q.pop();
Q.push(merge(qq,x,y));
}
return Q.front();
}
void newq(heap *q,int x,int val) { //新建元素
q[x].l=q[x].r=q[x].fa=0;
q[x].val=val;
}
int main() {
scanf("%d",&n);q[0].val=-inf;
for (int i=1;i<=n;i++) scanf("%d",&q[i].val);
rt=build();
scanf("%d",&m);
for (int x,y,i=1;i<=m;i++) {
scanf("%s",op);
if (op[0]=='U') {
scanf("%d%d",&x,&y);
int r1=find(q,x),r2=find(q,y);
if (r1!=r2) {
if (merge(q,r1,r2)==r1) rt=del(qq,r2);
else rt=del(qq,r1);
}
}
if (op[0]=='A') {
if (op[1]=='1') {
scanf("%d%d",&x,&y);
rt=del(qq,find(q,x));
int k=del(q,x);
newq(q,x,q[x].val+y);
k=merge(q,k,x);
newq(qq,k,q[k].val);
rt=merge(qq,k,rt);
}
if (op[1]=='2') {
scanf("%d%d",&x,&y);
int f=find(q,x);
q[f].val+=y;q[f].tag+=y;
rt=del(qq,f);
newq(qq,f,qq[f].val+y);
rt=merge(qq,rt,f);
}
if (op[1]=='3') scanf("%d",&y),Tag+=y;
}
if (op[0]=='F') {
if (op[1]=='1') {
scanf("%d",&x);
find(q,x),printf("%d\n",q[x].val+Tag);
}
if (op[1]=='2') {
scanf("%d",&x);
printf("%d\n",q[find(q,x)].val+Tag);
}
if (op[1]=='3') printf("%d\n",qq[rt].val+Tag);
}
}
return 0;
}

【bzoj2333】 SCOI2011—棘手的操作的更多相关文章

  1. 真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作

    n<=300000个点,开始是独立的,m<=300000个操作: 方法一:单点修改.查询,区间修改.查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两 ...

  2. BZOJ2333 [SCOI2011]棘手的操作 堆 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2333 题意概括 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i ...

  3. [bzoj2333] [SCOI2011]棘手的操作 (可并堆)

    //以后为了凑字数还是把题面搬上来吧2333 发布时间果然各种应景... Time Limit: 10 Sec  Memory Limit: 128 MB Description 有N个节点,标号从1 ...

  4. bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 读入所有数据,先模拟一遍所有的合并操作 我们不关心联通块长什么样,只关心联通块内有谁 所以可以 ...

  5. 2019.01.17 bzoj2333: [SCOI2011]棘手的操作(启发式合并)

    传送门 启发式合并菜题. 题意:支持与连通块有关的几种操作. 要求支持连边,单点修改,连通块修改,全局修改和单点查值,连通块查最大值和全局最大值. 我们对每个连通块和答案用可删堆维护最大值,然后用启发 ...

  6. BZOJ2333:[SCOI2011]棘手的操作(Splay)

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

  7. BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】

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

  8. bzoj2333 [SCOI2011]棘手的操作(洛谷3273)

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

  9. bzoj2333 [SCOI2011]棘手的操作

    用set维护每个联通块里的最值,multiset维护所有块里的最值,并查集维护连通性,然后随便搞搞就行了,合并时候采用启发式合并.复杂度O(nlognlogn),大概勉强过的程度,反正跑的很慢就是了. ...

  10. (右偏树)Bzoj2333: [SCOI2011]棘手的操作

    题面 戳我 Sol 右偏树滑稽+并查集 再在全局开一个可删除的堆(priority_queue) 注意细节 # include <bits/stdc++.h> # define RG re ...

随机推荐

  1. C# RSA加密/解密

    RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法, ...

  2. 浅谈html5某些新元素的用途

    大家都知道html是一种前端网页语言,从出现到现在已经经历了很多的版本了,但是随着html的不断发展,现在的html5已经不再是单一的前端页面语言了,html,javascript,css不再单纯的只 ...

  3. Java设计模式(学习整理)---策略模式

       1. 模式定义         把会变化的内容取出并封装起来,以便以后可以轻易地改动或扩充部分,而不影响不需要变化的其他部分: 2.模式本质:  少用继承,多用组合,简单地说就是:固定不变的信息 ...

  4. java问题整理

    1.一个“.java”源文件中是否可以包括多个类(不是内部类)?有什么限制? 答:可以有多个类.但只能有一个public类.并且public类名必须与文件名相一致.   2.Java有没有goto? ...

  5. SGU 113.Nearly prime numbers

    水一个代码: #include <iostream> using namespace std; int n, a; bool ok; bool prime (int x) { ; i * ...

  6. SGU 177.Square(矩阵分割)

    时间限制:1.25s 空间限制:6M 题意: 给出n*n的矩阵(n<=1000),和m次涂色(m<=5000),每次涂色将一个子矩阵涂成白色或黑色,后涂的颜色将覆盖掉前面的颜色.初始所有格 ...

  7. jquery中eq和get的区别与使用方法

    $("p").eq(0).css("color") //因为eq(num)返回的是个jq对象,所以可以用jq的方法css使用get来获得第一个p标签的color ...

  8. DEDE更改版权信息

    DEDECMSV5.7版本出现后,在前台网页底部会出现织梦版权信息 “powered by  dedecms”,很多人都不知道怎么去掉 1. 方法一: 在include/dedesql.classs. ...

  9. Unity NGUI 网络斗地主 -制作图集 Atlas

    Unity NGUI 网络斗地主 -制作图集 Atlas by @杨海龙 开发环境   Win7+Unity4.2.1f4+NGUI 3.0.4版本 这一节告诉大家如何制作(图集)Atlas! 1.首 ...

  10. KeilC51使用详解 (一)

    第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性.可维护性上有明显的优势,因而易学易用.用过 ...