题目描述

有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. 介绍静态链接库和动态链接库的差别,及在VC++6.0中的建立和使用

    首先介绍一下链接库:链接库分为动态链接库和静态链接库两种 LIB是静态链接库,在程序编译连接的时候是静态链接,其相应的文件格式是.lib. 即当程序採用静态链接库的时候..lib文件里的函数被链接到终 ...

  2. vdceye 最新中文界面

    最新的vdceye 的界面.左边菜单增加了问题.并增加了虚拟摄像机部分 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdmlkZW9fZGM=/font/5 ...

  3. 给一个执行在windows 7和NAT下的VMWARE虚拟机分配固定IP

    虚拟机上装了个oracleserver,每次vmware重新启动或者resume时总要分配新的IP地址,这样就得改动windows下的client配置,所以须要想办法把IP地址固定住. DHCP服务在 ...

  4. Swift的闭包,枚举,类和结构体

    闭包(Closures) 使用过其它语言的应该对代码块并不陌生,Swift中的闭包与C,OC中的Block相似. 表示自包括的函数代码块.能够在代码中传递和使用. 而且能够捕获和存储上下文的变量以及常 ...

  5. 《Java设计模式》之装饰模式

    装饰模式(Decorator) 1.    装饰模式(Decorator)的定义:又名包装(Wrapper)模式.装饰模式以对client透明的方式扩展对象的功能,是继承关系的一个替代方案. 2.   ...

  6. && 的用法

    document.body.style.display === "" && (document.body.style.display = "none&qu ...

  7. Windows 一键关闭UAC、防火墙、IE配置脚本

    有时候,在环境需求下,需要关闭windows防火墙,UAC,以及IE选项配置. 对不懂电脑来说是比较麻烦的,老是得教他们,关键还记不住…… so,以下脚本就可以解决这个问题 注:脚本 需要右键 以管理 ...

  8. 对比了解Grafana与Kibana的关键差异

    对比了解Grafana与Kibana的关键差异 http://www.infoq.com/cn/articles/grafana-vs-kibana-the-key-differences-to-kn ...

  9. [Android]新建项目继承Activity不继承ActionBarActivity

    在SDK更新后,在eclipse新建Android项目时.我们常常会碰到这样一种事情:新建的MainActivity不再继承Activity而是继承ActionBarActivity,因为一些人的开发 ...

  10. linux c statfs系统调用

    statfs 系统调用原型: int statfs(const char *path, struct statfs *buf); 參数说明: path : 位于须要查询信息的文件系统的路径名(不是设备 ...