【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$个字 ...
随机推荐
- 剖析Docker文件系统:Aufs与Devicemapper
http://www.infoq.com/cn/articles/analysis-of-docker-file-system-aufs-and-devicemapper Docker镜像 典型的Li ...
- Spring Data Jpa 初探
Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库.Map-Reduce 框架.云数据服务等等;另外也包含对关系数据库的访问支持. 下载网址: ...
- Python可视化Matplotlib-K线图
引入类库 import matplotlib as mpl import tushare as ts import matplotlib.pyplot as plt import matplotlib ...
- Myeclipse下配置struts2和hibernate
最近维护一个项目,是用struts2做的,所以特意学了下struts的入门,否则代码都看不懂啊.下面记录下过程.Myeclipse 版本为2014.struts2,hibernate为4.1. 1.既 ...
- 使用JCONSOLE远程监控JVM
启动JMS服务 JConsole是从Java 5中开始引入的一个用于对JVM性能和资源消耗进行监控的图形化工具.JConsole可以连接本地的Java程序,也可以连接远程的Java程序.由于是GUI的 ...
- SpringBean 定义继承
Bean定义继承 bean定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等.子bean的定义继承副定义的配置数据.子定义可以根据需要重写一些值 ...
- Selenium+Python学习之一
刚入门selenium+Python,实验成功之后,记录一下过程. 首先是在知乎上面看到一个关于selenium+python的示例,于是自己便尝试搭建环境上手实验. 按照作者的代码敲一遍之后执行,竟 ...
- Dom与Bom,增删改查
对Web标准的理解:web标准是由一系列标准组合而成的,页面有三个部分组成:结构,表现和行为.因而web标准即由结构化标准语言主要有 xml和xhtml,表现标准语言css,行为标准主要包括对象模型( ...
- ASP.NET Core EF 查询获取导航属性值,使用Include封装
// 引用 using Microsoft.EntityFrameworkCore; // 摘要: // Specifies related entities to include in the qu ...
- windows上使用clang编译程序
环境:windows7,64位 1.下载并安装llvm,安装包里除了llvm,也有clang: http://releases.llvm.org/5.0.0/LLVM-5.0.0-win64.exe ...