BZOJ 2333 SCOI2011 棘手的操作 可并堆套可并堆
来源:互联网 发布:nginx lua 获取header 编辑:程序博客网 时间:2024/06/06 23:17
题目大意:给定n个节点,每个节点有一个初始权值,维护以下操作:
1.合并两个联通块
2.某个点权值+x
3.某个点所在联通块权值+x
4.所有点权值+x
5.询问某个点的权值
6.询问某个点所在联通块的最大权值
7.询问所有点之间的最大权值
2333333333333333333333333333333333333333333333333333333333333
2333333333333333333333333333333333333333333333333333333333333
2333333333333333333333333333333333333333333333333333333333333
2333333333333333333333333333333333333333333333333333333333333
2333333333333333333333333333333333333333333333333333333333333
根据题目要求 对于每个联通块,我们需要一种数据结构,可以完成以下操作:
某个点权值+x
整体权值+x
查询某个点权值
查询最大值
合并
显然用可并堆就可以搞- -
那么12356我们就解决了
4只需要维护一个全局标记即可
7需要维护所有点的最大权值,我们很容易想到所有点的最大权值就是所有联通块最大权值的最大值
于是我们需要对所有联通块维护一个数据结构,支持:
插入某个点
删除某个点
修改某个点的权值
查询最大值
这不还是堆么!于是怒写可并堆套可并堆~
细节部分欢迎自行脑补,有益于身体健康~
TMD真是恶心死我了……
2333333333333333333333333333333333333333333333333333333333333333333
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 300300using namespace std;struct Heap{//内层随机堆Heap *ls,*rs,*fa;int val,mark;void Add(int x){val+=x;mark+=x;}void Push_Down(){if(!mark) return ;if(ls) ls->Add(mark);if(rs) rs->Add(mark);mark=0;}void _Push_Down(){if(fa) fa->_Push_Down();Push_Down();}void Cut(){_Push_Down();if(!fa) return ;if(this==fa->ls)fa->ls=0x0;elsefa->rs=0x0;fa=0x0;}Heap* Find_Root(){if(!fa) return this;return fa->Find_Root();}friend Heap* Merge(Heap *x,Heap *y){if(!x) return y;if(!y) return x;if(x->val<y->val)swap(x,y);y->fa=x;x->Push_Down();if(rand()&1)x->ls=Merge(x->ls,y);elsex->rs=Merge(x->rs,y);return x;}}heap2[M];struct abcd{//外层随机堆abcd *ls,*rs,*fa;Heap *root;void Cut(){if(!fa) return ;if(this==fa->ls)fa->ls=0x0;elsefa->rs=0x0;fa=0x0;}friend abcd* Merge(abcd *x,abcd *y){if(!x) return y;if(!y) return x;if(x->root->val<y->root->val)swap(x,y);y->fa=x;if(rand()&1)(x->ls=Merge(x->ls,y))->fa=x;else(x->rs=Merge(x->rs,y))->fa=x;return x;}}*root,heap1[M];abcd *belong[M];//记录每个内层堆堆顶在外层堆的位置int n,m,mark,a[M];void Union(int x,int y)//合并x和y所在堆{abcd *fx=belong[heap2[x].Find_Root()-heap2];abcd *fy=belong[heap2[y].Find_Root()-heap2];if(fx==fy) return ;if(fx->root->val<fy->root->val) swap(fx,fy);fy->Cut();if(fy==root) (root=Merge(root->ls,root->rs))->fa=0x0;else (root=Merge(root,Merge(fy->ls,fy->rs)))->fa=0x0;fx->root=Merge(fx->root,fy->root);belong[fx->root-heap2]=fx;}void Add1(int x,int y)//单点修改{abcd *fx=belong[heap2[x].Find_Root()-heap2];fx->Cut();heap2[x].Cut();abcd *temp1=Merge(fx->ls,fx->rs);if(temp1) temp1->fa=0x0;fx->ls=0x0;fx->rs=0x0;Heap *temp2=Merge(heap2[x].ls,heap2[x].rs);if(temp2) temp2->fa=0x0;heap2[x].ls=0x0;heap2[x].rs=0x0;heap2[x].val+=y;if(&heap2[x]!=fx->root)fx->root=Merge(fx->root,&heap2[x]);fx->root=Merge(fx->root,temp2);belong[fx->root-heap2]=fx;if(fx!=root)root=Merge(fx,root);root=Merge(root,temp1);}void Add2(int x,int y) //联通块修改{abcd *fx=belong[heap2[x].Find_Root()-heap2];fx->Cut();abcd *temp=Merge(fx->ls,fx->rs);if(temp) temp->fa=0x0;fx->ls=0x0;fx->rs=0x0;fx->root->Add(y);if(root!=fx) root=Merge(root,fx);root=Merge(root,temp);}void Add3(int y)//全体修改{mark+=y;}int Find1(int x)//单点查询{heap2[x]._Push_Down();return heap2[x].val+mark;}int Find2(int x)//联通块查询{return heap2[x].Find_Root()->val+mark;}int Find3()//整体查询{return root->root->val+mark;}int main(){freopen("2333.in","r",stdin);freopen("2333.out","w",stdout); int i,x,y;char p[10];srand(19980402);cin>>n;for(i=1;i<=n;i++){scanf("%d",&a[i]);heap1[i].root=&heap2[i];heap2[i].val=a[i];belong[i]=&heap1[i];root=Merge(root,&heap1[i]);}cin>>m;for(i=1;i<=m;i++){scanf("%s",p);if(p[0]=='U')scanf("%d%d",&x,&y),Union(x,y);if(p[0]=='A'){if(p[1]=='1')scanf("%d%d",&x,&y),Add1(x,y);if(p[1]=='2')scanf("%d%d",&x,&y),Add2(x,y);if(p[1]=='3')scanf("%d",&y),Add3(y);}if(p[0]=='F'){if(p[1]=='1')scanf("%d",&x),printf("%d\n",Find1(x));if(p[1]=='2')scanf("%d",&x),printf("%d\n",Find2(x));if(p[1]=='3')printf("%d\n",Find3());}}return 0;}
- [可并堆] BZOJ 2333 [SCOI2011]棘手的操作
- BZOJ 2333 SCOI2011 棘手的操作 可并堆套可并堆
- bzoj 2333: [SCOI2011]棘手的操作(线段树+离线操作,可并堆+set)
- [BZOJ2333][SCOI2011][可并堆]棘手的操作
- SCOI2011 Day2 棘手的操作 可并堆
- BZOJ 2333 SCOI 2011 棘手的操作 可并堆
- 【BZOJ2333】【SCOI2011】棘手的操作 可并堆+堆套堆(什么嘛,用个set就好啦)
- [BZOJ2333][SCOI2011]棘手的操作(可并堆||线段树+离线)
- [BZOJ2333][SCOI2011]棘手的操作(可并堆||线段树)
- BZOJ 2333: [SCOI2011]棘手的操作
- 【左偏树】【bzoj 2333】: [SCOI2011]棘手的操作
- BZOJ 2333 [SCOI2011]棘手的操作
- bzoj 2333: [SCOI2011]棘手的操作 离线+线段树
- bzoj2333 棘手的操作 可并堆or dfs序列+线段树
- bzoj2333: [SCOI2011]棘手的操作
- BZOJ2333: [SCOI2011]棘手的操作
- bzoj2333 [SCOI2011]棘手的操作
- bzoj2333[SCOI2011]棘手的操作
- javascript技巧:用闭包传递参数
- j2se的几种常用组件例子
- javascript 类型检测
- java编程思想之泛型类
- iOS面试四
- BZOJ 2333 SCOI2011 棘手的操作 可并堆套可并堆
- 1002. A+B for Polynomials (25)
- source openrc.sh
- 比较C++数组元素引用的两种形式a[0]与0[a]
- hibernate中SQLQuery的addEntity();方法
- 删除Mac中所有 .DS_Store 隐藏文件
- PHP缓存处理
- iOS给.h .m文件换名称
- Cannot find the class file for java.lang.Object