题目大意

  有\(n\)个节点,标号从1到\(n\),这\(n\)个节点一开始相互不连通。第\(i\)个节点的初始权值为\(a_i\),接下来有如下一些操作:

  \(U~x~y\):加一条边,连接第\(x\)个节点和第\(y\)个节点。

  \(A1~x~v\):将第\(x\)个节点的权值增加\(v\)。

  \(A2~x~v\):将第\(x\)个节点所在的连通块的所有节点的权值都增加\(v\)。

  \(A3~v\):将所有节点的权值都增加\(v\)。

  \(F1~x\):输出第\(x\)个节点当前的权值。

  \(F2~x\):输出第\(x\)个节点所在的连通块中,权值最大的节点的权值。

  \(F3\):输出所有节点中,权值最大的节点的权值。

  \(n,m\leq 300000,-1000\leq v,a_i\leq 1000\)

题解

  如果没有点修改就可以用可合并堆维护。但是现在有点修改,这样就需要遍历\(x\)到根。然而可合并堆的深度是\(O(n)\)的,这样做会直接TLE。

  那么还有没有什么其他的数据结构能支持合并和修改权值呢?

  答案是:有。可以用线段树或非旋treap。合并均摊是\(O(\log n)\)的。我选择了treap。

  treap合并在我的博客的另外一篇里面有写。

  再拿一棵树维护所有treap的最大值的最大值。

  用一个数维护全部节点的权值同时加了多少。输出时把这个加到答案上面去就可以了。

  时间复杂度:\(O((n+m)\log n)\)

  UPD:直接用treap的merge就行了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
struct node
{
int f,ls,rs;
int k,v,t,s;
int sz;
int u;
};
node a[300010];
int cnt=0;
int newnode(int u,int v)
{
int x=++cnt;
a[x].u=u;
a[x].v=a[x].s=v;
a[x].sz=1;
return x;
}
void add(int x,int v)
{
a[x].v+=v;
a[x].s+=v;
a[x].t+=v;
}
void push(int x)
{
if(a[x].t)
{
if(a[x].ls)
add(a[x].ls,a[x].t);
if(a[x].rs)
add(a[x].rs,a[x].t);
a[x].t=0;
}
}
void mt(int x)
{
a[x].s=a[x].v;
if(a[x].ls)
a[x].s=max(a[x].s,a[a[x].ls].s);
if(a[x].rs)
a[x].s=max(a[x].s,a[a[x].rs].s);
a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;
}
void pushdown(int x)
{
if(a[x].f)
pushdown(a[x].f);
push(x);
}
void pushup(int x)
{
mt(x);
if(a[x].f)
pushup(a[x].f);
}
int merge(int x,int y)
{
if(!x||!y)
return x+y;
if(a[x].k<a[y].k)
{
push(x);
a[x].rs=merge(a[x].rs,y);
mt(x);
if(a[x].rs)
a[a[x].rs].f=x;
return x;
}
else
{
push(y);
a[y].ls=merge(x,a[y].ls);
mt(y);
if(a[y].ls)
a[a[y].ls].f=y;
return y;
}
}
pii split(int x,int v)
{
if(!x)
return pii();
push(x);
if(v<a[x].u)
{
pii s=split(a[x].ls,v);
a[x].ls=s.second;
if(s.second)
a[s.second].f=x;
s.second=x;
a[x].f=0;
return s;
}
else
{
pii s=split(a[x].rs,v);
a[x].rs=s.first;
if(s.first)
a[s.first].f=x;
s.first=x;
a[x].f=0;
return s;
}
}
int join(int x,int y)
{
if(!x||!y)
return x+y;
if(a[x].k>a[y].k)
swap(x,y);
push(x);
pii s=split(y,a[x].v);
a[x].ls=merge(a[x].ls,s.first);
a[x].rs=merge(a[x].rs,s.second);
if(a[x].ls)
a[a[x].ls].f=x;
if(a[x].rs)
a[a[x].rs].f=x;
mt(x);
return x;
}
int f[300010];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int rt[300010];
multiset<int> s;
int main()
{
open("bzoj2333");
int n;
scanf("%d",&n);
int i,x;
for(i=1;i<=n;i++)
{
scanf("%d",&x);
rt[i]=newnode(i,x);
f[i]=i;
s.insert(x);
}
char op[5];
int y,v;
int all=0;
int m;
int ans;
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%s",op);
if(op[0]=='U')
{
scanf("%d%d",&x,&y);
x=find(x);
y=find(y);
if(x==y)
continue;
f[x]=y;
s.erase(s.find(min(a[rt[x]].s,a[rt[y]].s)));
rt[y]=join(rt[x],rt[y]);
}
else if(op[0]=='A'&&op[1]=='1')
{
scanf("%d%d",&x,&v);
y=find(x);
s.erase(s.find(a[rt[y]].s));
pushdown(x);
a[x].v+=v;
pushup(x);
s.insert(a[rt[y]].s);
}
else if(op[0]=='A'&&op[1]=='2')
{
scanf("%d%d",&x,&v);
x=find(x);
s.erase(s.find(a[rt[x]].s));
add(rt[x],v);
s.insert(a[rt[x]].s);
}
else if(op[0]=='A'&&op[1]=='3')
{
scanf("%d",&y);
all+=y;
}
else if(op[1]=='1')
{
scanf("%d",&x);
pushdown(x);
ans=a[x].v+all;
printf("%d\n",ans);
}
else if(op[1]=='2')
{
scanf("%d",&x);
x=find(x);
ans=a[rt[x]].s+all;
printf("%d\n",ans);
}
else
{
ans=*s.rbegin()+all;
printf("%d\n",ans);
}
}
return 0;
}

【BZOJ2333】【SCOI2011】棘手的操作 treap合并的更多相关文章

  1. 真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作

    n<=300000个点,开始是独立的,m<=300000个操作: 方法一:单点修改.查询,区间修改.查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两 ...

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

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

  3. 2019.01.17 bzoj2333: [SCOI2011]棘手的操作(启发式合并)

    传送门 启发式合并菜题. 题意:支持与连通块有关的几种操作. 要求支持连边,单点修改,连通块修改,全局修改和单点查值,连通块查最大值和全局最大值. 我们对每个连通块和答案用可删堆维护最大值,然后用启发 ...

  4. [bzoj2333] [SCOI2011]棘手的操作 (可并堆)

    //以后为了凑字数还是把题面搬上来吧2333 发布时间果然各种应景... Time Limit: 10 Sec  Memory Limit: 128 MB Description 有N个节点,标号从1 ...

  5. bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 读入所有数据,先模拟一遍所有的合并操作 我们不关心联通块长什么样,只关心联通块内有谁 所以可以 ...

  6. BZOJ2333 [SCOI2011]棘手的操作 堆 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2333 题意概括 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i ...

  7. BZOJ2333:[SCOI2011]棘手的操作(Splay)

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

  8. bzoj2333 [SCOI2011]棘手的操作(洛谷3273)

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

  9. bzoj2333 [SCOI2011]棘手的操作

    用set维护每个联通块里的最值,multiset维护所有块里的最值,并查集维护连通性,然后随便搞搞就行了,合并时候采用启发式合并.复杂度O(nlognlogn),大概勉强过的程度,反正跑的很慢就是了. ...

随机推荐

  1. JS判断当前设备类型

    CSS3出来后,我们一般都是通过@media媒体查询来实现网页自适应,但是有时候,还是需要我们根据不同的设备来对应的做不同的显示,这时候,我们需要知道当前用户访问我们的界面用的是什么设备,怎么获取呢? ...

  2. H5 71-网易注册界面4

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 小程序wxRequest封装

    //const host = 'http://114.215.00.00:8005';// 测试地址 const host = 'https://xx.xxxxxxxx.net'; // 正式地址 c ...

  4. ElasticSearch 分组查询的几个例子

    facets接口可以根据query返回统计数据,其中的 terms_stats 是分组统计,根据key的情况返回value的统计数据,类似group by的意思. "terms_stats& ...

  5. Python之加环境变量

    1.python找文件是先去当前文件所在的文件夹下找,也就是bin目录下找 2.如果bin目录里找不到,再去python的环境变量里找 如果有pycharm,那么直接点右键-选择Mark Direct ...

  6. 使用node操作mongodb

    let mongodb = require('mongodb'); let MongodbClient = mongodb.MongoClient; MongodbClient.connect('mo ...

  7. Tomcat Windows 系统下安装及注意事项

    1 获取Tomcat 安装包  http://tomcat.apache.org/ tar.gz 文件是Linux系统下的安装版本 exe文件是 Windows系统下的安装版本 zip 文件是Wind ...

  8. [日志]SAP S/4 HANA 启动与关闭的顺序

    注意 如果是非正式版的话 修改了日期了  需要重启一下应用和数据库才可以, S/4 HANA 启动步骤 先启动HANA: 在终端里输入 su - hdbadm HDB start 再启动S4 su - ...

  9. PostgreSQL 安装了contrib 之后 登录失败的问题

    1. 自己之前只是安装了 pg 10.6 2. 开发同事 需要用到 一个extensions 叫做 uuid-ossp 3. 执行报错  详情见昨天的blog 4. 然后执行了升级操作 结果 pg10 ...

  10. idea 最新破解亲测有效

    选择License serverLicense server address: 填:http://active.chinapyg.com/ (不能用了) 2018-5-7更新 新增一个 http:// ...