真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作
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]棘手的操作的更多相关文章
- [bzoj2333] [SCOI2011]棘手的操作 (可并堆)
//以后为了凑字数还是把题面搬上来吧2333 发布时间果然各种应景... Time Limit: 10 Sec Memory Limit: 128 MB Description 有N个节点,标号从1 ...
- BZOJ2333 [SCOI2011]棘手的操作 堆 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2333 题意概括 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i ...
- (右偏树)Bzoj2333: [SCOI2011]棘手的操作
题面 戳我 Sol 右偏树滑稽+并查集 再在全局开一个可删除的堆(priority_queue) 注意细节 # include <bits/stdc++.h> # define RG re ...
- 2019.01.17 bzoj2333: [SCOI2011]棘手的操作(启发式合并)
传送门 启发式合并菜题. 题意:支持与连通块有关的几种操作. 要求支持连边,单点修改,连通块修改,全局修改和单点查值,连通块查最大值和全局最大值. 我们对每个连通块和答案用可删堆维护最大值,然后用启发 ...
- BZOJ2333:[SCOI2011]棘手的操作(Splay)
Description 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 x v: ...
- BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】
题目 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 x v: 将第x个节点的权 ...
- bzoj2333[SCOI2011]棘手的操作 洛谷P3273 [SCOI2011]棘手的操作
2333? 先记一下吧,这题现在全部都是照着题解做的,因为怎么改都改不出来,只好对着题解改,以后还要再做过 以后再也不用指针了!太恶心了!空指针可不止直接特判那么简单啊,竟然还要因为空指针写奇怪的分类 ...
- bzoj2333 [SCOI2011]棘手的操作
用set维护每个联通块里的最值,multiset维护所有块里的最值,并查集维护连通性,然后随便搞搞就行了,合并时候采用启发式合并.复杂度O(nlognlogn),大概勉强过的程度,反正跑的很慢就是了. ...
- bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作
http://www.lydsy.com/JudgeOnline/problem.php?id=2333 读入所有数据,先模拟一遍所有的合并操作 我们不关心联通块长什么样,只关心联通块内有谁 所以可以 ...
随机推荐
- jmeter(十二)处理Cookie与Session
JMeter的工作原理是: JMeter可以作为Web服务器与浏览器之间的代理网关,以便捕获浏览器的请求和Web服务器的响应,这样就很容易地生成性能测试脚本, 有了性能测试脚本,JMeter就可以通过 ...
- ReactJS-0-React介绍
React介绍: React是一个库而不是一个MVC框架,因为React只负责解决MVC框架中V(View)层面的问题,React致力于创建可重用的UI组件.(React is a library f ...
- C#中的事件机制
这几天把事件学了一下,总算明白了一些.不多说了,直接代码. class Program { static void Main(string[] args) { CatAndMouse h = new ...
- 掌握Spark机器学习库-07.6-线性回归实现房价预测
数据集 house.csv 数据概览 代码 package org.apache.spark.examples.examplesforml import org.apache.spark.ml.fea ...
- iOS programming Code Snippet Library
iOS programming Code Snippet Library The freebie code comes from the code snippet library. 代码来自cod ...
- Objective -C Memory Management 内存管理 第一部分
Objective -C Memory Management 内存管理 第一部分 Memory management is part of a more general problem in pr ...
- windows sdk编程为应用程序添加图标
#include <windows.h> /*消息处理函数声明*/ HRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM ...
- ubuntu apt-update NO_PUBKEY 40976EAF437D05B5 NO_PUBKEY 3B4FE6ACC0B21F32
Fetched 28.1 MB in 11s (2344 kB/s) W: GPG error: http://archive.canonical.com xenial Release: The fo ...
- 用PHP怎么删除某目录下指定的一个文件
举个tp框架的例子 $User = M("message"); $a = $User->]['url']; unlink($url); $User->delete($i ...
- vue全选与反选以及通过使用如何filter删除数据
在vue学习经常遇到的一些基本问题,下面是购物车里面的部分功能,分享给初学者,直接上源码: <!DOCTYPE html><html> <head> <met ...