n<=300000个点,开始是独立的,m<=300000个操作:

方法一:单点修改、查询,区间修改、查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两棵树u,v时,把v放到u树根节点的最后,使其dfs序最后,最后扫一次把每棵树dfs一下搞出这个序列,然后线段树操作即可。

怎么把v放到u的儿子最后???强制一下连边顺序!!根据你写的邻接表,决定过程中的边是要正连还是倒连以达到目标顺序。有点抽象,见代码。

没写。

方法二:真正“棘手的操作”--可并堆!!!

如果是散散的点再连起来,可并堆的期望深度是小小的,可以做标记下传的!!

大体的思路是,每个块一个堆,然后每个堆的根节点的值再搞一个堆,就可以回答所有询问。然后来看看怎么操作:

U:直接合并。

A1:单点加,那就相当于单点查,单点删,单点加。单点删和单点加详见

单点查的话就标记下传就行了。。

A2:块加,打标记。

A3:是来搞笑的吗,记个全局变量。

F1:单点查,同上。

F2,F3:来搞笑的。

总之,重点在于:两个堆同时操作。

这次复合数据结构题的整体构思比以前有进步,但!!可并堆和并查集的结合非常混乱,这题要再写。

 #include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
//#include<assert.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n,m;
#define maxn 300011
struct leftist
{
struct Node
{
int fa,ls,rs,v,dis,add;
}a[maxn];
leftist() {a[].dis=-;}
void addsingle(int x,int v)
{
if (!x) return;
(a[x].v+=v);
a[x].add+=v;
}
void down(int x)
{
int &p=a[x].ls,&q=a[x].rs;
if (a[x].add) {addsingle(p,a[x].add); addsingle(q,a[x].add); a[x].add=;}
}
int sta[maxn];
void download(int x)
{
int top=;
for (int i=x;i;i=a[i].fa) sta[++top]=i;
for (;top;top--) down(sta[top]);
}
int merge(int x,int y)
{
if (!x || !y) return x^y;
if (a[x].v<a[y].v) {int t=x; x=y; y=t;}
down(x);
a[x].rs=merge(a[x].rs,y);
if (a[a[x].ls].dis<a[a[x].rs].dis) {int t=a[x].ls; a[x].ls=a[x].rs; a[x].rs=t;}
a[x].dis=a[a[x].rs].dis+;
if (a[x].rs) a[a[x].rs].fa=x; if (a[x].ls) a[a[x].ls].fa=x;
return x;
}
void Delete(int &root,int x)
{
int y=a[x].fa,w=(x==a[y].rs); x=merge(a[x].ls,a[x].rs); a[x].fa=y;
if (!y) {root=x; return;}
if (w) a[y].rs=x; else a[y].ls=x;
if (a[a[y].ls].dis<a[a[y].rs].dis) {int t=a[y].ls; a[y].ls=a[y].rs; a[y].rs=t;}
x=a[y].rs;
while (y && a[y].dis!=a[x].dis+)
{
a[y].dis=a[x].dis+;
x=y; y=a[y].fa;
if (a[a[y].ls].dis<a[a[y].rs].dis) {int t=a[y].ls; a[y].ls=a[y].rs; a[y].rs=t;}
x=a[y].rs;
}
}
void push(int id,int &root,int val)
{
a[id].fa=a[id].ls=a[id].rs=a[id].dis=a[id].add=; a[id].v=val;
root=merge(root,id);
}
int top(int root) {return a[root].v;}
}q,qtot;
int root[maxn];
int find(int x) {return x==root[x]?x:(root[x]=find(root[x]));} int main()
{
scanf("%d",&n);
for (int i=,x;i<=n;i++) scanf("%d",&x),q.push(i,root[i],x),qtot.push(i,root[],x);
scanf("%d",&m);
char c;int x,y; int totadd=;
for (int i=;i<=m;i++)
{
while ((c=getchar())!='U' && c!='A' && c!='F');
if (c=='U')
{
scanf("%d%d",&x,&y); x=find(x); y=find(y);
if (x==y) continue;
qtot.Delete(root[],y); qtot.Delete(root[],x);
root[x]=root[y]=q.merge(x,y);
x=root[x]; qtot.push(x,root[],q.a[x].v);
}
else if (c=='A')
{
c=getchar();
if (c=='')
{
scanf("%d%d",&x,&y); find(x);
qtot.Delete(root[],root[x]);
q.download(x); int tmp=q.a[x].v;
q.Delete(root[x],x); int z=root[x];
if (z) root[z]=z,q.push(x,root[z],tmp+y),root[x]=root[z];
else q.push(x,root[x],tmp+y);
qtot.push(root[x],root[],q.a[root[x]].v);
}
else if (c=='')
{
scanf("%d%d",&x,&y); x=find(x); qtot.Delete(root[],x);
q.addsingle(x,y); qtot.push(x,root[],q.a[x].v);
}
else if (c=='')
{
scanf("%d",&x);
totadd+=x;
}
}
else
{
c=getchar();
if (c=='')
{
scanf("%d",&x);
q.download(x);
printf("%d\n",q.a[x].v+totadd);
}
else if (c=='')
{
scanf("%d",&x); x=find(x);
printf("%d\n",q.a[x].v+totadd);
}
else printf("%d\n",qtot.a[root[]].v+totadd);
}
}
return ;
}

真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作的更多相关文章

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

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

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

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

  3. (右偏树)Bzoj2333: [SCOI2011]棘手的操作

    题面 戳我 Sol 右偏树滑稽+并查集 再在全局开一个可删除的堆(priority_queue) 注意细节 # include <bits/stdc++.h> # define RG re ...

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

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

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

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

  6. BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】

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

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

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

  8. bzoj2333 [SCOI2011]棘手的操作

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

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

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

随机推荐

  1. Spring注解驱动开发之声明式事务

    前言:现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解.原理,比如@Conditional.@Import.@Ena ...

  2. java课程设计全程实录——第3天

    参考资料: 课设主要指导: http://www.cnblogs.com/zhrb/p/6872265.html 2019年5月10日 https://blog.csdn.net/weixin_421 ...

  3. jmeter 连接 mysql 进行压力测试

  4. ios开发介绍

    iOS开发概述 •什么是IOS •什么是IOS开发 •为什么要选择IOS开发 •学习IOS开发的准备   1.什么是iOS   •iOS是一款由苹果公司开发的操作系统(OS是Operating Sys ...

  5. 让TortoiseGit记住帐号密码方法

    我的电脑环境是: Windows7 64x   系统用户名是:steden 所以,我的路径是:C:\Users\steden\ 具体要根据你的系统环境及当前用户名来决定. 在这里,有个文件:.gitc ...

  6. C++ 异常处理(try catch throw)、命名空间

    一.c++工具 模板(函数模板.类模板).异常处理.命名空间等功能是c++编译器的功能,语言本身不自带,这些功能已经成为ANSI C++标准了,建议所有的编译器都带这些功能,早期的c++是没有这些功能 ...

  7. CREATE OPERATOR CLASS - 定义一个新的操作符类

    SYNOPSIS CREATE OPERATOR CLASS name [ DEFAULT ] FOR TYPE data_type USING index_method AS { OPERATOR ...

  8. Vue beaforeCreate时获取data中的数据

    异步获取即:通过    $this.$nextTick或者settimeout,这连dom都可以拿出来 beforeCreate() { this.$nextTick(function() { con ...

  9. vue工程化之公有CSS、JS文件

    1.关于公共的css 在src下面新建public.css,然后在main.js中引入进来 import '@/public.css',这样所有页面中都会使用这个样式了,如果只是部分页面需要,那还是不 ...

  10. 对拍 bat命令快速模板

    对拍.bat @echo off :loop maker.exe > in.in wq.exe < in.in > out.out std.exe < in.in >st ...