传送门

线段树合并菜题(然而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. 生成二维码的JAVA

    不多说,上代码 package tcc; import java.awt.Color;import java.awt.Graphics2D;import java.awt.image.Buffered ...

  2. 成对使用new和delete,传值传引用

    首先: delete []p;是用来删除对象数组的,特别是你声明的是对象数组!!! 如果new中用了[],delete一定要用[]:在new中没有使用,在delete中一定不要使用. 其次: 当你使用 ...

  3. Delphi:基于jcl的Bugsplat Crash收集单元

    //BugSplat Crash模拟.net数据封装 unit uBugSplat; interface uses Windows, SysUtils, Classes, StrUtils, Shel ...

  4. linux下查看项目端口号,杀掉对应端口号的方法

    查看端口号:netstat -anp 结束端口号:sudo iptables -A INPUT -p tcp --dport 8012 -j DROP"

  5. jq里面关于disable的用法

    //两种方法设置disabled属性$('#areaSelect').attr("disabled",true);$('#areaSelect').attr("disab ...

  6. .net项目错误:找不到方法:“System.Net.Http.HttpClient stellar_dotnet_sdk.Server.get_HttpClient()

    1.由于在项目里面引用了一个 新的项目stellar_dotnet_sdk,在  return new StellarWallet(ConvertToWalletSetting(coin));   的 ...

  7. Windows下adobe Reader中pdf字体helvetica被替换为ArialMT

    笔者最近java项目中用itext-2.1.7导出pdf,使用了Helvetica,这个字体是内置的字体,本地Adobe Reader版本9.0 导出的文字是img.nur.cn实际效果 查看了pdf ...

  8. 基于.net技术的 Rss 订阅开发

    RSS(Really Simple Syndication,真正简单的连锁)是一种 Web 内容连锁格式.RSS 成为通过 Web 连锁新闻内容的标准格式.刚好我现在vs的环境也是.net,因为在.N ...

  9. Oracle_高级功能(1) 数据库设计

    1.三范式规范化关系模式称为范式.第一范式:在一个关系模型R中,如果R的每一个属性的值域中的值都是不可再分的最小数据单位, 则称R为第一范式(1NF).第二范式:如果一个关系模型R属于1NF,并且R的 ...

  10. 如何在Fragment中获取context

    文章转载自http://blog.csdn.net/demonliuhui/article/details/51511136 这里仅供自己学习参考: Context,中文直译为“上下文”,SDK中对其 ...