洛谷P3273 [SCOI2011]棘手的操作
题目描述
有N个节点,标号从1到N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:U x y: 加一条边,连接第x个节点和第y个节点A1 x v: 将第x个节点的权值增加vA2 x v: 将第x个节点所在的连通块的所有节点的权值都增加vA3 v: 将所有节点的权值都增加vF1 x: 输出第x个节点当前的权值F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值F3: 输出所有节点中,权值最大的节点的权值
输入输出格式
输入格式:
输入的第一行是一个整数N,代表节点个数。接下来一行输入N个整数,a[1], a[2], ..., a[N],代表N个节点的初始权值。再下一行输入一个整数Q,代表接下来的操作数。最后输入Q行,每行的格式如题目描述所示。
输出格式:
对于操作F1, F2, F3,输出对应的结果,每个结果占一行。
输入输出样例
说明
对于30%的数据,保证 N<=100,Q<=10000
对于80%的数据,保证 N<=100000,Q<=100000
对于100%的数据,保证 N<=300000,Q<=300000
对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], ..., a[N]<=1000
开两个可并堆堆
分别维护联通快最大值和所有的最大值
U x y: 加一条边,连接第x个节点和第y个节点
直接合并
A1 x v: 将第x个节点的权值增加v
先删掉,再加上原来的权值加v
A2 x v: 将第x个节点所在的连通块的所有节点的权值都增加v
跟线段树一样打个标记
A3 v: 将所有节点的权值都增加v
直接用一个变量记录
F1 x: 输出第x个节点当前的权值
直接输出
F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值
找到父亲,输出
F3: 输出所有节点中,权值最大的节点的权值
输出维护最大值的那个堆的根节点
效率暂时rank1
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int MAXN=;
#define ls T[x].ch[0]
#define rs T[x].ch[1]
inline int read()
{
int a;
cin>>a;
return a;
}
int root,N,All;
struct Priority
{
struct node
{
int fa,dis,val,ch[],mark;
}T[MAXN];
void Clear(int x){ls=rs=;T[x].fa=;}
void Pushdown(int x)
{
if(ls) T[ls].val+=T[x].mark,T[ls].mark+=T[x].mark;
if(rs) T[rs].val+=T[x].mark,T[rs].mark+=T[x].mark;
T[x].mark=;
}
int Merge(int x,int y)
{
if(!x||!y) return x+y;
if( T[x].val < T[y].val) swap(x,y);
Pushdown(x);
rs=Merge(rs,y);
T[rs].fa=x;
if(T[rs].dis>T[ls].dis) swap(ls,rs);
T[x].dis=T[rs].dis+;
return x;
}
int Delet(int x)
{
Pushdown(x);
int q=T[x].fa,p=Merge(ls,rs);
T[p].fa=q;
T[q].ch[ T[q].ch[] == x] = p;
while(q)
{
if(T[ T[q].ch[] ].dis < T[ T[q].ch[] ].dis) swap( T[q].ch[] , T[q].ch[] );
if(T[ T[q].ch[] ].dis+ == T[q].dis) return root;
T[q].dis=T[ T[q].ch[] ].dis+;
p=q;q=T[q].fa;
}
return p;
}
int Find(int x)
{
while(T[x].fa) x=T[x].fa;
return x;
}
int Sum(int x)
{
int ans=;
while(x=T[x].fa) ans+=T[x].mark;
return ans;
}
int AddPoint(int x,int v)
{
int fx=Find(x);
if(fx==x)
{
if(ls+rs==)
{T[x].val+=v;return x;}
else
if(ls) fx=ls;
else fx=rs;
}
Delet(x);
T[x].val+=v+Sum(x);
Clear(x);
return Merge(Find(fx),x);
}
int Build()
{
queue<int>q;
for(int i=;i<=N;i++)
q.push(i);
while(q.size()>)
{
int x=q.front();q.pop();
int y=q.front();q.pop();
int z=Merge(x,y);
q.push(z);
}
return q.front();
}
};
Priority h1,h2;
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
freopen("b.out","w",stdout);
#else
#endif
char opt[];
N=read();
h1.T[].dis=h2.T[].dis=-;
for(int i=;i<=N;i++)
h2.T[i].val=h1.T[i].val=read();
root=h2.Build();
int M=read();
while(M--)
{
scanf("%s",opt+);
if(opt[]=='U')
{
int x=read(),y=read();
int fx=h1.Find(x),fy=h1.Find(y);
if(fx!=fy)
{
int tmp=h1.Merge(fx,fy);
if(tmp==fx) root=h2.Delet(fy);
else root=h2.Delet(fx);//优化,根据大根堆的性质,以后的就没有用了
}
}
else if(opt[]=='A')
{
if(opt[]=='')
{
int x=read(),v=read();
root=h2.Delet(h1.Find(x));
int y=h1.AddPoint(x,v);
h2.T[y].val=h1.T[y].val;
h2.Clear(y);
root=h2.Merge(root,y);
}
else if(opt[]=='')
{
int x=read(),v=read();
int fx=h1.Find(x);
root=h2.Delet(fx);
h1.T[fx].val+=v;
h1.T[fx].mark+=v;
h2.T[fx].val=h1.T[fx].val;
h2.Clear(fx);
root=h2.Merge(root,fx);
}
else if(opt[]=='')
{
int v=read();
All+=v;
} }
else if(opt[]=='F')
{
if(opt[]=='')
{
int x=read();
printf("%d\n",h1.T[x].val+h1.Sum(x)+All);
}
else if(opt[]=='')
{
int x=read();
printf("%d\n",h1.T[h1.Find(x)].val+All);
}
else if(opt[]=='')
printf("%d\n",h2.T[root].val+All);
}
}
}
洛谷P3273 [SCOI2011]棘手的操作的更多相关文章
- 洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]
题目传送门 棘手的操作 题目描述 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 ...
- bzoj2333[SCOI2011]棘手的操作 洛谷P3273 [SCOI2011]棘手的操作
2333? 先记一下吧,这题现在全部都是照着题解做的,因为怎么改都改不出来,只好对着题解改,以后还要再做过 以后再也不用指针了!太恶心了!空指针可不止直接特判那么简单啊,竟然还要因为空指针写奇怪的分类 ...
- 洛谷.3273.[SCOI2011]棘手的操作(左偏树)
题目链接 还是80分,不是很懂. /* 七个操作(用左偏树)(t2表示第二棵子树): 1.合并:直接合并(需要将一个t2中原有的根节点删掉) 2.单点加:把这个点从它的堆里删了,加了再插入回去(有负数 ...
- P3273 [SCOI2011]棘手的操作
吐槽 上午风浔凌julao问我的神题 操作又多又毒瘤又棘手... 然后bzoj题号正好是2333,2333333333 思路 貌似只有我是这么写的 线段树合并, 每个线段树存每个连通块的信息,维护点的 ...
- Luogu P3273 [SCOI2011]棘手的操作(左偏树)
什么恶心东西啊,又水又烦 两个可并堆维护即可 #include <cstdio> #include <iostream> #include <cstring> #i ...
- 【bzoj2333】 [SCOI2011]棘手的操作 可并堆+lazy标记
2016-05-31 21:45:41 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2333 (学习了黄学长的代码 有如下操作: U x y ...
- 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树)
2333: [SCOI2011]棘手的操作 Description 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边 ...
- 2333: [SCOI2011]棘手的操作[写不出来]
2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1979 Solved: 772[Submit][Stat ...
- 2333: [SCOI2011]棘手的操作[离线线段树]
2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2325 Solved: 909[Submit][Stat ...
随机推荐
- 洛谷 P1583 魔法照片
P1583 魔法照片 题目描述 一共有n(n≤20000)个人(以1--n编号)向佳佳要照片,而佳佳只能把照片给其中的k个人.佳佳按照与他们的关系好坏的程度给每个人赋予了一个初始权值W[i].然后将初 ...
- Whats the difference between git reset --mixed, --soft, and --hard?
https://stackoverflow.com/questions/3528245/whats-the-difference-between-git-reset-mixed-soft-and-ha ...
- 21. 【intellij idea】Project Structure 讲解
转自:.https://www.cnblogs.com/zadomn0920/p/6196962.html 项目的左侧面板 项目设置->Project Project Settings -> ...
- 安装vnc出现的问题
重启vnc 命令:/sbin/service vncserver start或者vncserver VNC的启动/停止/重启 #service vncserver start/stop/restart ...
- POJ 3265 DP
思路: f[i][j]表示前i天能做j道题 (是做 不是做完) if(f[i-1][k]) if(suma[j]-suma[k]+g[i-1][k]<=n) f[i][j]=1,g[i][j]= ...
- 关于HTML5和CSS3的几个“新增”
html5和css3分别是目前最新的web前端编程的标准,加入了新的标准和要求. 1.HTML5新增input输入类型,即type后面的值 文本域 <input type="text& ...
- element-ui表格控件前端分页方法
<div id="app"> <el-table :data="tableData.slice((currentPage-1)*pageSize,cur ...
- Java的位运算符——&0xFF的运算与讲解
快放元旦假,没心思做啥的事,就去翻以前的代码遇到这句,但是又不懂,所以只好上网找,终于懂了那么一点点. 所以那个大神看到我说的有问题,请指出!谢谢.... 一:首先区分一下 A~F的意思先 A,代表十 ...
- 【v2.x OGE教程 12】 关卡编辑器帮助文档
] 关卡编辑器帮助文档 一.简单介绍 关卡编辑器用于游戏关卡界面元素的可视化编辑,包含元素的位置.尺寸以及其他自己定义属性.通过解析生成的数据文件就可以获取关卡信息,并能随时调整.以降低开发工作量,提 ...
- STL heap部分源代码分析
本文假设你已对堆排序的算法有主要的了解. 要分析stl中heap的源代码的独到之处.最好的办法就是拿普通的代码进行比較.话不多说,先看一段普通的堆排序的代码: //调整大顶堆.使得结构合理 void ...