题目描述

有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,输出对应的结果,每个结果占一行。

输入输出样例

输入样例#1: 复制

3
0 0 0
8
A1 3 -20
A1 2 20
U 1 3
A2 1 10
F1 3
F2 3
A3 -10
F3
输出样例#1: 复制

-10
10
10

说明

对于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]棘手的操作的更多相关文章

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

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

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

    2333? 先记一下吧,这题现在全部都是照着题解做的,因为怎么改都改不出来,只好对着题解改,以后还要再做过 以后再也不用指针了!太恶心了!空指针可不止直接特判那么简单啊,竟然还要因为空指针写奇怪的分类 ...

  3. 洛谷.3273.[SCOI2011]棘手的操作(左偏树)

    题目链接 还是80分,不是很懂. /* 七个操作(用左偏树)(t2表示第二棵子树): 1.合并:直接合并(需要将一个t2中原有的根节点删掉) 2.单点加:把这个点从它的堆里删了,加了再插入回去(有负数 ...

  4. P3273 [SCOI2011]棘手的操作

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

  5. Luogu P3273 [SCOI2011]棘手的操作(左偏树)

    什么恶心东西啊,又水又烦 两个可并堆维护即可 #include <cstdio> #include <iostream> #include <cstring> #i ...

  6. 【bzoj2333】 [SCOI2011]棘手的操作 可并堆+lazy标记

    2016-05-31  21:45:41 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2333 (学习了黄学长的代码 有如下操作: U x y ...

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

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

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

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

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

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

随机推荐

  1. IDEA使用技巧汇总

    使用IDEA也有一段时间了,今天又看到了一个不错的IDEA视频,觉得对IDEA熟悉得更多了,在这里做下笔记,如下 视频链接:https://www.imooc.com/video/16219 1.下载 ...

  2. C++模板中重要的术语

  3. C# Winform利用POST传值方式模拟表单提交数据(Winform与网页交互)

    其原理是,利用winfrom模拟表单提交数据.将要提交的參数提交给网页,网页运行代码.得到数据.然后Winform程序将网页的全部源码读取下来.这样就达到windows应用程序和web应用程序之间传參 ...

  4. hdu 思维风暴

    点击打开链接 偶然在杭电上看到的题目,数学题.好像是一道六年级奥赛题目,反正我是没有想出来,也知道往那上面想.就是找不到规律啊.学习了网上的方法, 这道题须要求出来多添加的点,就是与之前每条边添加的点 ...

  5. X的追求道路

    X的追求道路 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述 X在大家的帮助下最终找到了一个妹纸,于是開始了漫漫的追求之路,那 ...

  6. Android Design Support Library初探,NavigationView实践

    前言 在前几天的IO大会上,Google带来了Android M,同时还有Android支持库的新一轮更新,其中更是增加一个全新的支持库Android Design Support Library,包 ...

  7. poj--2007--Scrambled Polygon(数学几何基础)

    Scrambled Polygon Time Limit: 1000MS   Memory Limit: 30000KB   64bit IO Format: %I64d & %I64u Su ...

  8. Vsftp问题及解决办法汇总(持续增加中)

    1.VsFTP出现500 OOPS: cannot change directory的解决办法 在安装完vsftp服务后登陆时可能遇到cannot change directory后面是登陆者的目录的 ...

  9. 14.c语言dll注入

    #include <Windows.h> //dll不需要main函数 //导出接口 _declspec(dllexport) void go() { MessageBoxA(, ); }

  10. HAProxy高可用配置视频教程

    HAProxy提供高可用性.负载均衡等,它是免费.快速并且可靠的一种解决方案.HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理.HAProxy运行在当前的硬件上, ...