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

。。题意概述就不写了,各位老爷如果是看着玩的可以去搜一下,如果是做题找来的也知道题干的。实际上是题干无法缩减懒得复制ORZ

首先处理一下集合的合并和单点值查询的问题。使用并查集,记录两个数组w,d:w记录对这个点单点操作的值,d记录对这个点代表的集合进行的操作累计的值,对于每个点find的时候把这个点到代表元路径上的点的d(不包括代表元)的d加起来更新这个点的d,每一次查询某个点的当前值的时候就先find就可以直接用w+d+代表元的d(特判这个点是不是代表元)回答。特别注意为了保证正确性在merge的时候要把双方中的某一个点建立成另外一个新点,原来两个点的pa是这个新点。这样值的集合修改和查询就解决。

接下来是最大值的问题。这里用的是可并堆。开两个可并堆,一个维护每个集合(称为hp1),另一个维护每个集合中的最大值(称为hp2)。有点lazy的思想,因为单点修改只会影响这个点的值,所以说直接在hp1中调整这个点的位置(注意到可能是向下,也可能是向上),然后看此集合中最大值对应的元素编号是否改变。改变的话就在hp2中删掉原来的最大元素编号加入新的,否则如果修改的这个点就是其集合中的最大值元素就在hp2中调整位置;如果是集合修改的话思路同单点直接调整被修改集合中最大值在hp2中的位置;对于所有值修改的操作直接单独记录一个数输出的时候加上就可以了(不影响单调性)。

这样调整之后任意时刻可并堆中的所有元素的位置都是正确的,正确性得以保证(虽然这个自己yy出来的东西代码有点长?)

最后说一件事情,自己乱搞数据结构的时候一定注意。。。。。指针要改完改对。。。。。

细节参见代码。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int MAXN=; int N,Q,A[MAXN];
struct union_find{
static const int maxn=;
int pa[maxn<<],stk[maxn<<],d[maxn<<],id[maxn<<],w[maxn<<],stk_top,np,ADD;
union_find(){ np=stk_top=ADD=; };
int newnode(int x) { w[++np]=x,pa[np]=np,d[np]=; return np; }
void initial(int n,int *a){
for(int i=;i<=n;i++) pa[i]=id[i]=i,w[i]=a[i],d[i]=;
np=n;
}
int find(int x)
{
while(pa[x]!=x) stk[++stk_top]=x,x=pa[x];
int rt=x,add=;
while(stk_top) x=stk[stk_top],add+=d[x],d[x]=add,pa[x]=rt,stk_top--;
return rt;
}
int val(int x) { find(x); return w[x]+d[x]+(pa[x]==x?:d[pa[x]])+ADD; }
bool judge(int x,int y) { return find(x)==find(y); }
void merge(int x,int y) { pa[find(x)]=pa[find(y)]=newnode(val(y)-ADD); }
}uf;
struct mergeable_heap{
static const int maxn=;
int chd[maxn][],fa[maxn];
void initial(int n) { for(int i=;i<=n;i++) chd[i][]=chd[i][]=fa[i]=; }
int val(int x) { return uf.val(uf.id[x]); }
void link(int x,int d,int y) { chd[x][d]=y,fa[y]=x; }
int root(int x) { while(fa[x]) x=fa[x]; return x; }
int merge(int A,int B)
{
if(!A||!B) return A+B;
if(val(A)<val(B)) swap(A,B);
link(A,,merge(chd[A][],B)); swap(chd[A][],chd[A][]);
return A;
}
void ins(int A,int B) { fa[A]=chd[A][]=chd[A][]=; merge(A,B); }
void del(int A)
{
if(A==root(A)) fa[merge(chd[A][],chd[A][])]=;
else{
int d=A==chd[fa[A]][];
link(fa[A],d,merge(chd[A][],chd[A][]));
}
}
int top(int x) { return val(root(x)); }
void rot(int x)
{
int p=fa[x],e=x==chd[p][];
int a=chd[x][],b=chd[x][],c=chd[p][e],d=fa[p];
link(p,,a); link(p,,b);
link(x,,e?p:c); link(x,,e?c:p);
link(d,chd[d][]==p,x);
}
void adjust(int x)
{
while(fa[x]&&val(x)>val(fa[x])) rot(x);
while(chd[x][]||chd[x][]){
int y;
if(!chd[x][]||!chd[x][]) y=chd[x][]?chd[x][]:chd[x][];
else y=val(chd[x][])>val(chd[x][])?chd[x][]:chd[x][];
if(val(y)<=val(x)) break;
rot(y);
}
}
}hp1,hp2; void _scanf(char &x)
{
x=getchar();
while(x!='U'&&x!='A'&&x!='F') x=getchar();
}
void data_in()
{
scanf("%d",&N);
for(int i=;i<=N;i++) scanf("%d",&A[i]);
scanf("%d",&Q);
}
void work()
{
uf.initial(N,A);
hp1.initial(N); hp2.initial(N);
for(int i=;i<N;i++)
hp2.merge(hp2.root(i),i+);
char op1; int op2,x,y,v,rx,ry;
for(int i=;i<=Q;i++){
_scanf(op1);
if(op1=='U'){
scanf("%d%d",&x,&y);
if(!uf.judge(uf.id[x],uf.id[y])){
rx=hp1.root(x),ry=hp1.root(y);
uf.merge(uf.id[x],uf.id[y]);
hp1.merge(rx,ry);
if(rx!=hp1.root(x)) hp2.del(rx); else hp2.del(ry);
}
}
else if(op1=='A'){
scanf("%d",&op2);
if(op2==){
scanf("%d%d",&x,&v);
rx=hp1.root(x);
uf.w[uf.id[x]]+=v; hp1.adjust(x);
if(rx!=hp1.root(x)){
int rt=max(hp2.fa[rx],max(hp2.chd[rx][],hp2.chd[rx][]));
hp2.del(rx); rt=hp2.root(rt);
hp2.ins(hp1.root(x),rt);
}
else if(rx==x) hp2.adjust(x);
}
else if(op2==){
scanf("%d%d",&x,&v);
uf.d[uf.find(uf.id[x])]+=v;
hp2.adjust(hp1.root(x));
}
else if(op2==) scanf("%d",&v),uf.ADD+=v;
}
else if(op1=='F'){
scanf("%d",&op2);
if(op2==) scanf("%d",&x),printf("%d\n",hp1.val(x));
else if(op2==) scanf("%d",&x),printf("%d\n",hp1.top(x));
else if(op2==) printf("%d\n",hp2.top(hp1.root()));
}
}
}
int main()
{
data_in();
work();
return ;
}

BZOJ 2333 SCOI2011 棘手的操作 并查集+可并堆的更多相关文章

  1. BZOJ 2333: [SCOI2011]棘手的操作

    题目描述 真的是个很棘手的操作.. 注意每删除一个点,就需要clear一次. #include<complex> #include<cstdio> using namespac ...

  2. BZOJ 2333 [SCOI2011]棘手的操作 (可并堆)

    码农题.. 很显然除了两个全局操作都能用可并堆完成 全局最大值用个multiset记录,每次合并时搞一搞就行了 注意使用multiset删除元素时 如果直接delete一个值,会把和这个值相同的所有元 ...

  3. BZOJ 2333: [SCOI2011]棘手的操作 可并堆 左偏树 set

    https://www.lydsy.com/JudgeOnline/problem.php?id=2333 需要两个结构分别维护每个连通块的最大值和所有连通块最大值中的最大值,可以用两个可并堆实现,也 ...

  4. bzoj 2333 [SCOI2011]棘手的操作 —— 可并堆

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2333 稍微复杂,参考了博客:http://hzwer.com/5780.html 用 set ...

  5. 2333: [SCOI2011]棘手的操作[离线线段树]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2325  Solved: 909[Submit][Stat ...

  6. 2333: [SCOI2011]棘手的操作[写不出来]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1979  Solved: 772[Submit][Stat ...

  7. 2333: [SCOI2011]棘手的操作[我不玩了]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1979  Solved: 772[Submit][Stat ...

  8. 【BZOJ】2333: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 题意: 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i], ...

  9. 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树)

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

随机推荐

  1. 轻量ORM-SqlRepoEx 重大升级

    .Net平台下兼容.NET Standard 2.0,一个实现以Lambda表达式转转换标准SQL语句,支持MySQL.SQL Server数据库方言,使用强类型操作数据的轻量级ORM工具,在减少魔法 ...

  2. Oracle 差异性增量 和 累计增量 原理(转)

    RMAN一个强大的功能是支持增量备份,增量备份中心思想就是减少备份的数据量,我们不需要在从头开始备份了,只需要备份自上次已备份之后的数据块即可.   Oracle 9i 共有五种级别 0 1 2 3 ...

  3. SQL3120W 不能将xx的字段值转换成 INTEGER值

    一次用DB2 Load/Import导入数据时,报错,提示SQL3120W 不能将xx的字段值转换成 INTEGER值,但目标列不可为空.未装入该行. 目标表: CREATE TABLE TEST( ...

  4. <寒假逆向学习第一天> 破解基础知识之介绍常见工具和壳的特征

    对于我们新手来说,程序是什么语言编写的?程序到底有没有加壳?程序加了什么壳?一直在我们心中充满了疑惑,本文我将根据我的近期学习,总结一下常见的工具和壳的特征. 一:程序是什么语言编译的 从目前接触到程 ...

  5. For macOS.百度网盘 破解SVIP、下载速度限制~

    For macOS.百度网盘 破解SVIP.下载速度限制~ 是插件的 https://github.com/CodeTips/BaiduNetdiskPlugin-macOS 2019-01-03 让 ...

  6. SpringBoot配置全局自定义异常

    不同于传统集中时Springmvc 全局异常,具体查看前面的章节https://www.cnblogs.com/zwdx/p/8963311.html 对于springboot框架来讲,这里我就介绍一 ...

  7. LintCode 12.带最小值操作的栈(两种方法实现)

    题目描述 实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 样例 如下操作:push(1 ...

  8. 使用Win32DiskImager后重置SD卡

    再1.Windows diskpart命令 diskpart 2.列出所有的磁盘 lisk disk 3.选择U盘所在的磁盘 4.清除磁盘 clean 5.创建主分区 create primary p ...

  9. maven-认识

    1.认识maven maven是强大的项目构建工具,也是依赖管理工具 使用maven前提是安装JDK maven非常重要配置文件:setting.xml 3.maven工程 maven工程的约束: 主 ...

  10. mysql中tinyint、smallint、mediumint,int 和bigint 的区别

    1:字节的定义:字节(Byte):字节是通过网络传输信息(或在硬盘或内存中存储信息)的单位. 一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间 2.在mysql中一个汉字占三个 ...