传送门

线段树合并菜题(然而findfindfind函数写错位置调了好久)

支持的操作题目写的很清楚了,然后有一个神奇的限制c≤7c\le7c≤7要注意到不然会去想毒瘤线段树的做法。


思路:

这题只有一个新奇的操作就是比较两个连通块的所有点权的乘积的大小。

这个东西可以对所有点权取对数之后转化为比较加和的大小。

剩下的都可以用并查集+线段树合并秒掉。

注意题目卡空间

代码:

#include<bits/stdc++.h>
#define lc (son[p][0])
#define rc (son[p][1])
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=4e5+5;
struct Npde{int op,a,b;}qry[N];
int son[N*18][2],siz[N*18],tot=0,rt[N],fa[N],mp[N],n,m,cnt=0;
double val[N*18];
bool tag[N*18];
inline void pushup(int p){siz[p]=siz[lc]+siz[rc],val[p]=val[lc]+val[rc];}
inline void pushnow(int p){val[p]=siz[p]=0,tag[p]=1;}
inline void pushdown(int p){if(tag[p])pushnow(lc),pushnow(rc),tag[p]=0;}
inline void build(int&p,int l,int r,int k,int v1,double v2){
	if(!p)p=++tot;
	if(l==r){siz[p]=v1,val[p]=v2;return;}
	int mid=l+r>>1;
	pushdown(p);
	k<=mid?build(lc,l,mid,k,v1,v2):build(rc,mid+1,r,k,v1,v2);
	pushup(p);
}
inline int merge(int x,int y,int l,int r){
	if(!x||!y)return x+y;
	siz[x]+=siz[y],val[x]+=val[y];
	if(l==r)return x;
	int mid=l+r>>1;
	pushdown(x),pushdown(y);
	son[x][0]=merge(son[x][0],son[y][0],l,mid);
	son[x][1]=merge(son[x][1],son[y][1],mid+1,r);
	return x;
}
inline int query(int p,int l,int r,int ql,int qr){
	if(!p||ql>r||qr<l)return 0;
	if(ql<=l&&r<=qr)return siz[p];
	int mid=l+r>>1;
	pushdown(p);
	if(qr<=mid)return query(lc,l,mid,ql,qr);
	if(ql>mid)return query(rc,mid+1,r,ql,qr);
	return query(lc,l,mid,ql,mid)+query(rc,mid+1,r,mid+1,qr);
}
inline void update(int p,int l,int r,int ql,int qr){
	if(!p||ql>r||qr<l)return;
	if(ql<=l&&r<=qr)return pushnow(p);
	int mid=l+r>>1;
	pushdown(p);
	if(qr<=mid)update(lc,l,mid,ql,qr);
	else if(ql>mid)update(rc,mid+1,r,ql,qr);
	else update(lc,l,mid,ql,mid),update(rc,mid+1,r,mid+1,qr);
	pushup(p);
}
inline int ask(int p,int l,int r,int k){
	if(l==r)return l;
	int mid=l+r>>1;
	pushdown(p);
	if(siz[lc]>=k)return ask(lc,l,mid,k);
	return ask(rc,mid+1,r,k-siz[lc]);
}
inline int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);}
inline int idx(int x){return lower_bound(mp+1,mp+n+1,x)-mp;}
int main(){
	m=read();
	for(ri i=1;i<=m;++i){
		qry[i].op=read(),qry[i].a=read();
		if(qry[i].op!=1&&qry[i].op!=7)qry[i].b=read();
		if(qry[i].op==1)mp[++n]=qry[i].a;
		if(qry[i].op==3||qry[i].op==4)mp[++n]=qry[i].b;
	}
	sort(mp+1,mp+n+1),n=unique(mp+1,mp+n+1)-mp-1;
	for(ri i=1;i<=m;++i){
		switch(qry[i].op){
			case 1:build(rt[++cnt],1,n,idx(qry[i].a),1,log2(qry[i].a)),fa[cnt]=cnt;break;
			case 2:{
				int fx=find(qry[i].a),fy=find(qry[i].b);
				if(fx^fy)fa[fy]=fx,rt[fx]=merge(rt[fx],rt[fy],1,n);
				break;
			}
			case 3:{
				int fx=find(qry[i].a);
				int p=idx(qry[i].b),s=query(rt[fx],1,n,1,p);
				update(rt[fx],1,n,1,p),build(rt[fx],1,n,p,s,s*log2(qry[i].b));
				break;
			}
			case 4:{
				int fx=find(qry[i].a);
				int p=idx(qry[i].b),s=query(rt[fx],1,n,p,n);
				update(rt[fx],1,n,p,n),build(rt[fx],1,n,p,s,s*log2(qry[i].b));
				break;
			}
			case 5:cout<<mp[ask(rt[find(qry[i].a)],1,n,qry[i].b)]<<'\n';break;
			case 6:cout<<(val[rt[find(qry[i].a)]]>val[rt[find(qry[i].b)]])<<'\n';break;
			case 7:cout<<siz[rt[find(qry[i].a)]]<<'\n';break;
		}
	}
	return 0;
}

2019.01.16 bzoj4399: 魔法少女LJJ(线段树合并)的更多相关文章

  1. BZOJ4399魔法少女LJJ——线段树合并+并查集

    题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉人的奶浆味: ...

  2. bzoj4399 魔法少女LJJ 线段树合并

    只看题面绝对做不出系列.... 注意到\(c \leqslant 7\),因此不会有删边操作(那样例删边干嘛) 注意到\(2, 5\)操作十分的有趣,启示我们拿线段树合并来做 操作\(7\)很好处理 ...

  3. bzoj4399 魔法少女LJJ 线段树合并+线段树二分+并查集

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4399 题解 毒瘤题 \(9\) 种操作还有支持动态图的连通性 仔细读题 $ c<=7$. ...

  4. 【BZOJ4399】魔法少女LJJ 线段树合并

    [BZOJ4399]魔法少女LJJ Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的 ...

  5. BZOJ 4399: 魔法少女LJJ 线段树合并 + 对数

    Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着 ...

  6. BZOJ.4399.魔法少女LJJ(线段树合并)

    BZOJ 注意\(c\leq7\)→_→ 然后就是裸的权值线段树+线段树合并了. 对于取\(\max/\min\)操作可以直接区间修改清空超出范围的值,然后更新到对应位置上就行了(比如对\(v\)取\ ...

  7. 魔法少女 LJJ——线段树

    题目 [题目描述] 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女 LJJ 已经觉得自己见过世界上的所有稀奇古怪的事情了. LJJ 感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处 ...

  8. BZOJ 4399: 魔法少女LJJ(线段树)

    传送门 解题思路 出题人真会玩..操作\(2\)线段树合并,然后每棵线段树维护元素个数和.对于\(6\)这个询问,因为乘积太大,所以要用对数.时间复杂度\(O(nlogn)\) 代码 #include ...

  9. 2019.01.16 bzoj3526: [Poi2014]Card(线段树)

    传送门 线段树菜题. 题意:有一些卡牌,正反各有一个数,你可以任意翻转,每次操作会将两张卡牌的位置调换,你需要在每次操作后回答以现在的卡牌顺序能否通过反转形成一个单调不降的序列. 思路: 对于一个线段 ...

随机推荐

  1. HDU5532 Almost Sorted Array(最长上升子序列 or 瞎搞个做差的数组)

    题目链接:点我 题意:给定一个序列,询问是否能删除一个数让它成为非递减或者非递增的序列. 比如说 删除后的序列是1 3 3 5 或者5 3 3 1 或者1 3 5 或者5 3 1 都可以.只要满足删掉 ...

  2. java 異常抛出 throw 與 return

    package 異常;    public class TestException {      public TestException() {      }        boolean test ...

  3. TZOJ 数据结构期末历年题目

    A.数据结构练习题――线性表操作 线性表的基本操作 1.在某个位置p插入val,复杂度O(p) 2.在某个位置p删除val,复杂度O(p) 3.查找某个位置p的值,复杂度O(p) 4.清除链表,复杂度 ...

  4. jmeter操作数据库,分布式,在Linux上运行

    jmeter操作数据库: 1.在测试计划中导入数据库jar包 2.添加链接数据库信息 3.mysql:jdc:mysql://192.168.1.116:3307/bugfree?allowMulti ...

  5. 42-2017蓝桥杯b java

    1.购物单    小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞.    这不,XX大促销又来了!老板夫人开出了长长的购物单,都 ...

  6. node.js中对同步,异步,阻塞与非阻塞的理解

    我们都知道javascript是单线程的,node.js是一个基于Chrome V8 引擎的 javascript 运行时环境,注意 node.js 不是一门语言,别搞错了. javascript为什 ...

  7. DNS的过程

    来自:https://www.zhihu.com/question/23042131 作者:郭无心链接:https://www.zhihu.com/question/23042131/answer/6 ...

  8. 地图调起URI API(通过连接直接调用百度地图)

    网站:http://lbsyun.baidu.com/index.php?title=uri/api/web 地图调起URI API 百度地图URI API是为开发者提供直接调起百度地图产品(百度We ...

  9. js 实现的简易计算器

    <!DOCTYPE html><html lang="zh-CN"><head> <!-- <meata charset='utf- ...

  10. PHP的网站主要攻击方式有哪些?

    1.命令注入(Command Injection) 2.eval注入(Eval Injection) 3.客户端脚本攻击(Script Insertion) 4.跨网站脚本攻击(Cross Site ...