题意

https://www.lydsy.com/JudgeOnline/problem.php?id=4399

思路

码农题,需要一定代码功底。方法很暴力,先将权值离散,表示在线段树里储存的位置,每个连通块用一棵动点线段树存储,合并两个连通块直接对两个动点线段树进行合并,查询操作在当前连通块的线段树上进行,只不过有询问乘积大小,直接权值取原权值的 \(\ln​\) ,比较和的大小即可。

现在分析线段树合并的复杂度,举一个最基本的例子:权值为\([1,n]\) ,\(n\) 棵动点线段树,每个线段树插入了一个权值,那么总共有 \(n\log n\) 个点,而每一次合并相当于少掉了一个点,那么合并完这 \(n\) 棵线段树后复杂度就是消失的点的个数,不会超过总共的点数,所以复杂度是 \(n \log n\) 的。

类似的,对最一般的情况,也是一样的分析方法,最后得出线段树合并的复杂度为节点个数的结论。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
typedef long long LL;
using namespace std;
const int N=4e5+5;
const int NN=N*12; struct SegmentTree
{
struct node
{
int cnt;double sum;
node operator +(const node &_)const
{
return (node){cnt+_.cnt,sum+_.sum};
}
};
node nd[NN];
int lson[NN],rson[NN],rt[N],tot;
int &operator [](const int x){return rt[x];}
void build()
{
memset(rt,0,sizeof(rt));
nd[tot=0]=(node){0,0};
lson[0]=rson[0]=0;
}
void create(int &k)
{
if(!k)k=++tot,nd[k]=nd[0],lson[k]=rson[k]=0;
}
void update(int &k,int x,int addcnt,double addsum,int l,int r)
{
create(k);
if(l==r)
{
nd[k].cnt+=addcnt;
nd[k].sum+=addsum;
return;
}
int mid=(l+r)>>1;
if(x<=mid)update(lson[k],x,addcnt,addsum,l,mid);
else update(rson[k],x,addcnt,addsum,mid+1,r);
nd[k]=nd[lson[k]]+nd[rson[k]];
}
int sweep_off(int &k,int L,int R,int l,int r)
{
if(!k)return 0;
if(L<=l&&r<=R){int res=nd[k].cnt;k=0;return res;}
int mid=(l+r)>>1,res=0;
if(L<=mid)res+=sweep_off(lson[k],L,R,l,mid);
if(R>mid)res+=sweep_off(rson[k],L,R,mid+1,r);
nd[k]=nd[lson[k]]+nd[rson[k]];
return res;
}
int querycnt(int k){return nd[k].cnt;}
double querysum(int k){return nd[k].sum;}
int queryKth(int k,int K,int l,int r)
{
if(l==r)return l;
int mid=(l+r)>>1;
if(nd[lson[k]].cnt>=K)return queryKth(lson[k],K,l,mid);
else return queryKth(rson[k],K-nd[lson[k]].cnt,mid+1,r);
}
void merge(int &x,int y,int l,int r)
{
if(!x||!y){x=(x|y);return;}
if(l==r){nd[x]=nd[x]+nd[y];return;}
int mid=(l+r)>>1;
merge(lson[x],lson[y],l,mid);
merge(rson[x],rson[y],mid+1,r);
nd[x]=nd[lson[x]]+nd[rson[x]];
}
}ST;
int n,m,fa[N];
int op[N],a[N],b[N];
int disc[N],tot;
double logdisc[N];
int getfa(int k){return k==fa[k]?k:fa[k]=getfa(fa[k]);} int main()
{
scanf("%d",&m);
FOR(i,1,m)
{
scanf("%d%d",&op[i],&a[i]);
if(op[i]!=1&&op[i]!=7)scanf("%d",&b[i]);
} FOR(i,1,m)
{
if(op[i]==1)disc[++tot]=a[i];
else if(op[i]==3||op[i]==4)disc[++tot]=b[i];
}
sort(disc+1,disc+1+tot);
tot=unique(disc+1,disc+1+tot)-disc-1;
FOR(i,1,m)
{
if(op[i]==1)a[i]=lower_bound(disc+1,disc+1+tot,a[i])-disc;
else if(op[i]==3||op[i]==4)b[i]=lower_bound(disc+1,disc+1+tot,b[i])-disc;
}
FOR(i,1,tot)logdisc[i]=log(disc[i]); ST.build();
FOR(i,1,m)
{
if(op[i]==1)
{
n++;
fa[n]=n;
ST.update(ST[n],a[i],1,logdisc[a[i]],1,tot);
}
else if(op[i]==2)
{
a[i]=getfa(a[i]),b[i]=getfa(b[i]);
if(a[i]==b[i])continue;
ST.merge(ST[a[i]],ST[b[i]],1,tot);
fa[b[i]]=a[i];
}
else if(op[i]==3)
{
if(b[i]==1)continue;
a[i]=getfa(a[i]);
int cnt=ST.sweep_off(ST[a[i]],1,b[i]-1,1,tot);
ST.update(ST[a[i]],b[i],cnt,cnt*logdisc[b[i]],1,tot);
}
else if(op[i]==4)
{
if(b[i]==tot)continue;
a[i]=getfa(a[i]);
int cnt=ST.sweep_off(ST[a[i]],b[i]+1,tot,1,tot);
ST.update(ST[a[i]],b[i],cnt,cnt*logdisc[b[i]],1,tot);
}
else if(op[i]==5)
{
a[i]=getfa(a[i]);
printf("%d\n",disc[ST.queryKth(ST[a[i]],b[i],1,tot)]);
}
else if(op[i]==6)
{
a[i]=getfa(a[i]),b[i]=getfa(b[i]);
if(ST.querysum(ST[a[i]])>ST.querysum(ST[b[i]]))
puts("1");
else puts("0");
}
else if(op[i]==7)
{
a[i]=getfa(a[i]);
printf("%d\n",ST.querycnt(ST[a[i]]));
}
} return 0;
}

BZOJ 4399 魔法少女LJJ(线段树合并)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. bzoj 4399 魔法少女LJJ

    4399: 魔法少女LJJ Time Limit: 20 Sec  Memory Limit: 162 MBhttp://www.lydsy.com/JudgeOnline/problem.php?i ...

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

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

随机推荐

  1. Spark学习之路 (五)Spark伪分布式安装

    一.JDK的安装 JDK使用root用户安装 1.1 上传安装包并解压 [root@hadoop1 soft]# tar -zxvf jdk-8u73-linux-x64.tar.gz -C /usr ...

  2. [DeploymentService:290066]Error occurred while downloading files from admin server for deployment request "0". Underlying error is: "null"

    weblogic 莫名无法启动: <Apr , :: PM CST> <Error> <Deployer> <BEA-> <Failed to i ...

  3. Java -cp 命令查看 zookeeper 日志

  4. python range函数

    这个函数很简单,就不写例子了,看看语法,拿来即用 python range() 函数可创建一个整数列表,一般用在 for 循环中. 函数语法 range(start, stop[, step]) 参数 ...

  5. 微信小程序制作家庭记账本之二

    第二天,继续学习制作记账本,网上搜寻别人的源码进行学习,但是搜寻过程中总是能看到github这个东西,不清楚这是什么东西,明天继续努力吧.

  6. 关于Weex你需要知道的一切

    QCon第一天,GMTC全球移动技术大会联席主席.手淘技术老大庄卓然(花名南天)在Keynote上宣布跨平台开发框架Weex开始内测,并将于6月份开源,同时他们也放出官网:http://alibaba ...

  7. Different between MB SD Connect Compact 5 and MB SD C4 Star Diagnostic Tool

    MB SD C4 Star Diagnostic Tool is the professional MB Star Diagnostic Tools for benz cars and trucks. ...

  8. 细数那些不懂Spring底层原理带来的伤与痛

    1. 什么是spring? Spring 是个Java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标是简化Jav ...

  9. Python Selenium element is not reachable by keyboard

    碰到这个问题,没法解决, 最后这么搞的 pcAction.move_by_offset(571, 534).click().perform() #激活输入框 driver.switch_to.acti ...

  10. Python - mouse clicks and keystrokes on a background window

    https://stackoverflow.com/questions/43965437/python-mouse-clicks-and-keystrokes-on-a-background-wind ...