题目描述

在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了
LJJ感叹道“这里真是个迷人的绿色世界,空气清新、淡雅,到处散发着醉人的奶浆味;小猴在枝头悠来荡去,好不自在;各式各样的鲜花争相开放,各种树枝的枝头挂满沉甸甸的野果;鸟儿的歌声婉转动听,小河里飘着落下的花瓣真是人间仙境”
SHY觉得LJJ还是太naive,一天,SHY带着自己心爱的图找到LJJ,对LJJ说:“既然你已经见识过动态树,动态仙人掌了,那么今天就来见识一下动态图吧”
LJJ:“要支持什么操作?”
SHY:“
1.新建一个节点,权值为x。
2.连接两个节点。
3.将一个节点a所属于的联通快内权值小于x的所有节点权值变成x。
4.将一个节点a所属于的联通快内权值大于x的所有节点权值变成x。
5.询问一个节点a所属于的联通块内的第k小的权值是多少。
6.询问一个节点a所属联通快内所有节点权值之积与另一个节点b所属联通快内所有节点权值之积的大小。
7.询问a所在联通快内节点的数量
8.若两个节点a,b直接相连,将这条边断开。
9.若节点a存在,将这个点删去。

LJJ:“我可以离线吗?”
SHY:“可以,每次操作是不加密的,”
LJJ:“我可以暴力吗?”
SHY:“自重”
LJJ很郁闷,你能帮帮他吗

(事实上,仔细读题可以发现,出题人在数据范围中约定了$c\le 7$,因此第8、9种操作是不存在的!这里也将样例作了修改)

输入

第一行有一个正整数m,表示操作个数。
接下来m行,每行先给出1个正整数c。
若c=1,之后一个正整数x,表示新建一个权值为x的节点,并且节点编号为n+1(当前有n个节点)。
若c=2,之后两个正整数a,b,表示在a,b之间连接一条边。
若c=3,之后两个正整数a,x,表示a联通快内原本权值小于x的节点全部变成x。
若c=4,之后两个正整数a,x,表示a联通快内原本权值大于x的节点全部变成x。
若c=5,之后两个正整数a,k,表示询问a所属于的联通块内的第k小的权值是多少。
若c=6,之后两个正整数a,b,表示询问a所属联通快内所有节点权值之积与b所属联通快内所有节点权值之积的大小,
若a所属联通快内所有节点权值之积大于b所属联通快内所有节点权值之积,输出1,否则为0。
若c=7,之后一个正整数a,表示询问a所在联通块大小
若c=8,之后两个正整数a,b,表示断开a,b所连接的边。
若c=9,之后一个正整数a,表示断开a点的所有连边
具体输出格式见样例

输出

对于每个询问,输出答案

样例输入

11
1 2
1 3
1 4
1 5
1 6
2 1 2
2 2 3
2 3 4
2 4 5
3 2 5
5 3 4

样例输出

5


题解

并查集+权值线段树合并(本题是道语文题= =)

对于操作1、2、3、4、5、7,稍有做题经验的人很容易想到使用并查集维护连通块,对每个连通块开一棵权值线段树。

连边操作直接权值线段树合并,各种查询直接裸上线段树的区间查询。

对于3、4操作,可以先统计出有多少个数小于/大于x,然后删除所有小于/大于x的数,并在x位置加上这些数。

而对于6操作出现了乘积不是很好处理,我们把它取对数,因为$\log(nm)=\log n+\log m$,所以转化为每个数的对数的和,直接维护区间权值和即可。本题中使用double不会被卡精度。

时间复杂度$O(m\log n)$。

然而比$O(m\log n+n\log^2n)$的平衡树启发式合并还慢什么鬼。。

#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 400010
#define lson l , mid , ls[x]
#define rson mid + 1 , r , rs[x]
using namespace std;
const int m = 1000000000;
int ls[N * 19] , rs[N * 19] , si[N * 19] , tot , root[N] , f[N] , n;
double sum[N * 19];
bool tag[N * 19];
void pushdown(int x)
{
if(tag[x])
{
si[ls[x]] = si[rs[x]] = 0 , sum[ls[x]] = sum[rs[x]] = 0;
tag[ls[x]] = tag[rs[x]] = 1 , tag[x] = 0;
}
}
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
void add(int p , int a , double v , int l , int r , int &x)
{
if(!x) x = ++tot;
si[x] += a , sum[x] += a * v;
if(l == r) return;
pushdown(x);
int mid = (l + r) >> 1;
if(p <= mid) add(p , a , v , lson);
else add(p , a , v , rson);
}
void del(int b , int e , int l , int r , int x)
{
if(!x) return;
if(b <= l && r <= e)
{
si[x] = 0 , sum[x] = 0 , tag[x] = 1;
return;
}
pushdown(x);
int mid = (l + r) >> 1;
if(b <= mid) del(b , e , lson);
if(e > mid) del(b , e , rson);
si[x] = si[ls[x]] + si[rs[x]] , sum[x] = sum[ls[x]] + sum[rs[x]];
}
int querysi(int b , int e , int l , int r , int x)
{
if(!x) return 0;
if(b <= l && r <= e) return si[x];
pushdown(x);
int mid = (l + r) >> 1 , ans = 0;
if(b <= mid) ans += querysi(b , e , lson);
if(e > mid) ans += querysi(b , e , rson);
return ans;
}
int find(int k , int l , int r , int x)
{
if(l == r) return l;
pushdown(x);
int mid = (l + r) >> 1;
if(k <= si[ls[x]]) return find(k , lson);
else return find(k - si[ls[x]] , rson);
}
int merge(int x , int y)
{
if(!x) return y;
if(!y) return x;
si[x] += si[y] , sum[x] += sum[y];
pushdown(x) , pushdown(y);
ls[x] = merge(ls[x] , ls[y]) , rs[x] = merge(rs[x] , rs[y]);
return x;
}
int main()
{
int q , c , x , y , t;
scanf("%d" , &q);
while(q -- )
{
scanf("%d%d" , &c , &x);
switch(c)
{
case 1: add(x , 1 , log(x) , 1 , m , root[++n]) , f[n] = n; break;
case 2:
{
scanf("%d" , &y) , x = find(x) , y = find(y);
if(x != y) f[y] = x , root[x] = merge(root[x] , root[y]);
break;
}
case 3:
{
x = find(x) , scanf("%d" , &y) , t = querysi(1 , y , 1 , m , root[x]);
del(1 , y , 1 , m , root[x]) , add(y , t , log(y) , 1 , m , root[x]);
break;
}
case 4:
{
x = find(x) , scanf("%d" , &y) , t = querysi(y , m , 1 , m , root[x]);
del(y , m , 1 , m , root[x]) , add(y , t , log(y) , 1 , m , root[x]);
break;
}
case 5: x = find(x) , scanf("%d" , &y) , printf("%d\n" , find(y , 1 , m , root[x])); break;
case 6: x = find(x) , scanf("%d" , &y) , y = find(y) , printf("%d\n" , sum[root[x]] > sum[root[y]]); break;
default: x = find(x) , printf("%d\n" , si[root[x]]);
}
}
return 0;
}

【bzoj4399】魔法少女LJJ 并查集+权值线段树合并的更多相关文章

  1. bzoj 2733: [HNOI2012]永无乡【并查集+权值线段树】

    bzoj上数组开大会T-- 本来想用set瞎搞的,想了想发现不行 总之就是并查集,每个点开一个动态开点的权值线段树,然后合并的时候把值并在根上,询问的时候找出在根的线段树里找出k小值,看看这个值属于哪 ...

  2. luogu3224 永无乡(动态开点,权值线段树合并)

    luogu3224 永无乡(动态开点,权值线段树合并) 永无乡包含 n 座岛,编号从 1 到 n ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 n 座岛排名,名次用 1 到 n 来表示.某些 ...

  3. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

  4. 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并

    题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...

  5. 【bzoj4719】[Noip2016]天天爱跑步 权值线段树合并

    题目描述 给出一棵n个点的树,以及m次操作,每次操作从起点向终点以每秒一条边的速度移动(初始时刻为0),最后对于每个点询问有多少次操作在经过该点的时刻为某值. 输入 第一行有两个整数N和M .其中N代 ...

  6. 【bzoj2212】[Poi2011]Tree Rotations 权值线段树合并

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826614.html 题目描述 Byteasar the gardener is growing a rare tr ...

  7. 【bzoj3307】雨天的尾巴 权值线段树合并

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y,对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来 ...

  8. HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)

    layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...

  9. BZOJ2733/LG3324 「HNOI2014」永无乡 权值线段树合并

    问题描述 BZOJ2733 LG3224 题解 对于每个结点建立一棵权值线段树. 查询操作就去查询第 \(k\) 大,合并操作就合并两颗权值线段树. 并查集维护连通性. 同时 STO hkk,zcr, ...

随机推荐

  1. python读取excel中的数据

    import numpy as np import matplotlib.pyplot as plt import pandas as pd #df = pd.read_excel('/Users/N ...

  2. 一些常用的集合工具的代码块(缓慢更新XD,更新了多属性过滤:) )

    更新记录 虽然经常放鸽子,但是还是要记录一下更新 2017.8.30 更新了listToMap的方法,现在可以指定多个属性进行分组了,例如你要指定一个学生集合,按照名字和年龄相同的放在一组,现在只要调 ...

  3. Websocket教程SpringBoot+Maven整合

    1.大话websocket及课程介绍 简介: websocket介绍.使用场景分享.学习课程需要什么基础 2.课程技术选型和浏览器兼容讲解 简介: 简单介绍什么是springboot.socketjs ...

  4. windows2012服务器搭建mongodb并设置远程访问

    因为python脚本需要用到mongodb,而且需要本地查看数据库,所以就在腾讯云的windows服务器上部署了mongodb服务器,因为网上大部分教程是针对linux的自己搜索走了很多坑,这里记录下 ...

  5. 03_14_final关键字

    03_14_final关键字 1. Final关键字 final的变量的值不能够被改变 final的成员变量 final的局部变量(形参) final的方法不能够被重写 final的类不能够被继承

  6. Spring+ ApplicationListener

    有时候 需要在容器初始化完成后,加载些 代码字典或不常变的信息  放入缓存之类的,这里使用spring 初始化bean,并实例化 1.创建一个ApplicationListener类 import o ...

  7. 六、MySQL 删除数据库

    MySQL 删除数据库 使用普通用户登陆 MySQL 服务器,你可能需要特定的权限来创建或者删除 MySQL 数据库,所以我们这边使用 root 用户登录,root 用户拥有最高权限. 在删除数据库过 ...

  8. stark组件(2):提取公共视图函数、URL分发和设置别名

    效果图: Handler类里处理的增删改查.路由分发.给URL设置别名等包括以后还要添加的很多功能,每一个数据库的类都需要,所以我们要把Handler提取成一个基类.提取成基类后,每一个数据表都可以继 ...

  9. 用iTerm快速链接远程服务器

    通常情况下,iTerm2访问远程Linux使用ssh ssh <用户名>@<ip> 然后输入访问的密码即可.当然还有的时候需要指定访问端口. ssh -p <端口号> ...

  10. Fliptile POJ - 3279 (开关问题)

    Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16483   Accepted: 6017 Descrip ...