传送门

线段树合并菜题(然而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. 颜色 color

    在res/values文件夹下的color.xml添加 <?xml version="1.0" encoding="utf-8"?> <res ...

  2. PHPlaravel中从数据库中选择数据是增加时间条件及各种条件

    注:附加条件后要加get函数. 1.public function getForDataTable($startTime,$endTime){ return $this->query() -&g ...

  3. ASCII码翻译方法可直接使用谷歌

    ASCII码翻译方法可直接使用谷歌. 如: key{you are right} 将此段ASCII码输入谷歌搜索栏,直接翻译结果:    

  4. stm32 启动文件 C和汇编交叉嵌入

    在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的.在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,主要是因为C语言的结构比较 ...

  5. Topological Sorting拓扑排序

    定义: Topological Sorting is a method of arranging the vertices in a directed acyclic graph (DAG有向无环图) ...

  6. C# 创建WebService的简单示例

    工具Visual Studio 2013 1.创建一个空的Web应用程序. 2.鼠标右击项目,添加->新建项 选择Web服务(ASMX),点击添加.一个简单的webservice就创建完成了.

  7. 64位Win7系统下vs2010调试无法连接oracle解决办法

    具体的解决办法如下: 1.先将WebDev.WebServer20.EXE和WebDev.WebServer40.EXE文件从Program Files (x86)目录中拷贝出来放到c:\dev目录中 ...

  8. iOS.XcodeUsage

    1. Customizing Xcode File Templates http://blog.highorderbit.com/2009/03/15/customizing-xcode-cocoa- ...

  9. 2019年Java未来的发展方向

    2018即将结束,迎来2019年,Java作为世界上 最流行的计算机编程语言,在当今信息时代中发挥了重要的作用.Java语言本身具有着自己独特的优势:面向对象.分布式应用并且安全.多线程.跨平台等.这 ...

  10. 如何在Windows下安装Tomcat服务器

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选服务器.在Windows下安装 ...