【bzoj2333 & luoguP3273】棘手的操作(线段树合并)
题目传送门:bzoj2333 luoguP3273
这操作还真“棘手”。。听说这题是可并堆题?然而我不会可并堆。于是我就写了线段数合并,然后调了一晚上,数据结构毁一生!!!QAQ……
其实这题也可以把合并强行看成树上的关系然后dfs序后直接线段树的,然而我菜啊。。看到连边就只能想到线段树合并。
首先用并查集维护图的连通性,然后对于每个连通块建一棵下标为点的编号的线段树,于是:
U=合并两棵树;
A1:单点加;
A2:区间加;
A3:因为是整体加,所以我们可以维护一个delta表示当前每个数被整体加了多少,然后输出时直接加上就好了;
F1:单点查询;
F2:区间查询;
然而还有一个F3整体查询最大值很难处理。于是我再开了一颗线段树,维护每个连通块内的最大值,修改时顺便在上面修改信息,F3操作可以直接在树上查询。
时间复杂度$ O(n \log n) $,然而常数极大。
两颗线段树+奇奇怪怪的维护方法,使写出来的代码膨胀到了3.6kB……然后,调试++,and then,(如果你写的不优美)MLE+TLE。经过了一番痛苦的调试后,终于过了。。。QAQ
又臭又长的代码:
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 300010
inline ll read()
{
ll x=; char c=getchar(),f=;
for(;c<''||''<c;c=getchar())if(c=='-')f=-;
for(;''<=c&&c<='';c=getchar())x=x*+c-'';
return x*f;
}
struct segment_tree1{
struct point{
int lc,rc,mx,delta;
}sgt[*maxn];
int tot;
void add(int now,int l,int r,int x,int y,int k)
{
if(x<=l&&r<=y)sgt[now].delta+=k,sgt[now].mx+=k;
else{
int mid=(l+r)>>;
if(x<=mid){
if(!sgt[now].lc)sgt[now].lc=++tot;
add(sgt[now].lc,l,mid,x,y,k);
}
if(mid<y){
if(!sgt[now].rc)sgt[now].rc=++tot;
add(sgt[now].rc,mid+,r,x,y,k);
}
sgt[now].mx=std::max(sgt[sgt[now].lc].mx,sgt[sgt[now].rc].mx);
if(sgt[now].mx!=-inf)sgt[now].mx+=sgt[now].delta;
}
}
int getmax(int now,int l,int r,int x,int y)
{
if(x<=l&&r<=y)return sgt[now].mx;
else{
int mid=(l+r)>>,mx=-inf;
if(x<=mid&&sgt[now].lc)mx=std::max(mx,getmax(sgt[now].lc,l,mid,x,y));
if(mid<y&&sgt[now].rc)mx=std::max(mx,getmax(sgt[now].rc,mid+,r,x,y));
return mx+sgt[now].delta;
}
}
void merge(int x,int y,int d)
{
d+=sgt[y].delta-sgt[x].delta;
if(!sgt[x].lc)sgt[x].lc=sgt[y].lc,sgt[sgt[x].lc].delta+=d,sgt[sgt[x].lc].mx+=d;
else if(sgt[y].lc)merge(sgt[x].lc,sgt[y].lc,d);
if(!sgt[x].rc)sgt[x].rc=sgt[y].rc,sgt[sgt[x].rc].delta+=d,sgt[sgt[x].rc].mx+=d;
else if(sgt[y].rc)merge(sgt[x].rc,sgt[y].rc,d);
sgt[x].mx=std::max(sgt[sgt[x].lc].mx,sgt[sgt[x].rc].mx)+sgt[x].delta;
}
}t1;
struct segment_tree2{
struct point{
int mx,delta;
}sgt[*maxn];
void add(int now,int l,int r,int x,int y,int k)
{
if(x<=l&&r<=y)sgt[now].delta+=k,sgt[now].mx+=k;
else{
int mid=(l+r)>>;
if(x<=mid)add(now<<,l,mid,x,y,k);
if(mid<y)add(now<<|,mid+,r,x,y,k);
sgt[now].mx=std::max(sgt[now<<].mx,sgt[now<<|].mx);
if(sgt[now].mx!=-inf)sgt[now].mx+=sgt[now].delta;
}
}
int getmax(int now,int l,int r,int x,int y)
{
if(x<=l&&r<=y)return sgt[now].mx;
else{
int mid=(l+r)>>,mx=-inf;
if(x<=mid)mx=std::max(mx,getmax(now<<,l,mid,x,y));
if(mid<y)mx=std::max(mx,getmax(now<<|,mid+,r,x,y));
return sgt[now].delta+mx;
}
}
}t2;
int rt[maxn],fa[maxn],a[maxn],delta;
int n,m;
char op[];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main()
{
n=read();
t1.tot=; delta=;
t1.sgt[].mx=t2.sgt[].mx=-inf;
for(int i=;i<=n;i++){
a[i]=read();
rt[i]=++t1.tot; fa[i]=i;
t1.add(rt[i],,n,i,i,a[i]);
t2.add(,,n,i,i,a[i]);
}
m=read();
for(int i=;i<=m;i++){
scanf("%s",op);
if(op[]=='U'){
int x=read(),y=read();
x=find(x); y=find(y);
if(x!=y){
fa[y]=x; t1.merge(rt[x],rt[y],);
t2.add(,,n,x,x,std::max(a[x],a[y])-a[x]); t2.add(,,n,y,y,-a[y]-inf);
a[x]=std::max(a[x],a[y]); a[y]=-inf;
}
}
else if(op[]=='A'){
if(op[]==''){
int x=read(),v=read(),fx=find(x);
t1.add(rt[fx],,n,x,x,v);
int t=t1.getmax(rt[fx],,n,,n);
t2.add(,,n,fx,fx,t-a[fx]);
a[fx]=t;
}
else if(op[]==''){
int x=read(),v=read(),fx=find(x);
t1.add(rt[fx],,n,,n,v);
t2.add(,,n,fx,fx,v);
a[fx]+=v;
}
else{
int v=read();
delta+=v;
}
}
else{
if(op[]==''){
int x=read(),fx=find(x);
printf("%d\n",t1.getmax(rt[fx],,n,x,x)+delta);
}
else if(op[]==''){
int x=read(),fx=find(x);
printf("%d\n",a[fx]+delta);
}
else printf("%d\n",t2.getmax(,,n,,n)+delta);
}
}
}
bzoj2333 & luoguP3273
可并堆的做法以后再补吧。。
【bzoj2333 & luoguP3273】棘手的操作(线段树合并)的更多相关文章
- 神奇的操作——线段树合并(例题: BZOJ2212)
什么是线段树合并? 首先你需要动态开点的线段树.(对每个节点维护左儿子.右儿子.存储的数据,然后要修改某儿子所在的区间中的数据的时候再创建该节点.) 考虑这样一个问题: 你现在有两棵权值线段树(大概是 ...
- 2019.01.17 bzoj2333: [SCOI2011]棘手的操作(启发式合并)
传送门 启发式合并菜题. 题意:支持与连通块有关的几种操作. 要求支持连边,单点修改,连通块修改,全局修改和单点查值,连通块查最大值和全局最大值. 我们对每个连通块和答案用可删堆维护最大值,然后用启发 ...
- 【BZOJ2333】棘手的操作(左偏树,STL)
[BZOJ2333]棘手的操作(左偏树,STL) 题面 BZOJ上看把... 题解 正如这题的题号 我只能\(2333\) 神TM棘手的题目... 前面的单点/联通块操作 很显然是一个左偏树+标记 ( ...
- [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】
题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...
- BZOJ2733 [HNOI2012]永无乡 【线段树合并】
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)
[bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...
- B20J_2733_[HNOI2012]永无乡_权值线段树合并
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...
- 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...
- BZOJ5417[Noi2018]你的名字——后缀自动机+线段树合并
题目链接: [Noi2018]你的名字 题目大意:给出一个字符串$S$及$q$次询问,每次询问一个字符串$T$有多少本质不同的子串不是$S[l,r]$的子串($S[l,r]$表示$S$串的第$l$个字 ...
随机推荐
- Nginx无法启动,80端口被PID=4占用
在nginx启动后,error.log中总是显示 80 端口被占用. 通过netstat -ano发现,其被一个叫PID=4的系统服务占用. 网上大多数的方法是说通过regidit修改注册表的方式解决 ...
- zipline风险指标计算 (empyrical模块)
概述 量化中,我们经常会遇到各种量化指标的计算,对于zipline来说,也会对这部分计算进行处理,由于指标计算的通用性比较强,所以,zipline单独封装了 empyrical 这个模块,可以处理类似 ...
- Python并行编程(十一):基于进程的并行
1.基本概念 多进程主要用multiprocessing和mpi4py这两个模块. multiprocessing是Python标准库中的模块,实现了共享内存机制,可以让运行在不同处理器核心的进程能读 ...
- 3类数据库的联动:mysql、mongodb、redis
3类数据库的联动:mysql.mongodb.redis from pymysql import * from pymongo import * from redis import * class M ...
- 使用CocoaPods管理第三方类库[效率]
项目文件夹 加入第三方框架后的项目文件夹例如以下图 为什么要用Cocoapods? iOS开发中经常使用的第三方库,比方: 1.FMDB:在使用SQLite是仅仅须要加入libsqlite3. ...
- SDUT3141:Count(哈希)好题
题目:传送门 题目描述 You are given an integer array s[] and are asked to count how many positions a, b, c and ...
- Spring基本功能-扫描与继承
一.Spring的扫描 一个稍大的项目中,可能会有成百上千个bean,此时采用xml的配置形式注入bean,一方面是配置文件显得十分庞大,另一方面也会导致后期的维护难度增加,为 此,Spring引入了 ...
- 使用JS实现页面倒数计数
<script type="text/javascript"> var number = 5; function showNum(){ if(number==1){ w ...
- 存储库之——MongoDB
阅读目录 一 简介 二 MongoDB基础知识 三 安装 四 基本数据类型 五 CRUD操作 六 可视化工具 七 pymongo 一 简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1. ...
- Restful风格API
一:协议 API与用户的通信协议,总是使用HTTPS协议. 二:域名 应该尽量将API部署在专用域名之下. https://api.example.com 如果确定API很简单,不会有进一步扩展,可以 ...