将所有权值离散化,建立权值线段树,维护区间内数字个数以及对数的和,用于比较乘积大小。

对于每个连通块维护一棵权值线段树,合并时用线段树合并。

对于操作3和4,暴力删除所有不合法节点,然后一并修改后插入线段树即可。

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

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=400010,M=7000000;
int n,m,i,x,y,op[N][3],b[N],U,f[N],T[N],cnt;
int tot,l[M],r[M],v[M];double s[M],L[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline int lower(int x){
int l=1,r=U,mid,t;
while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
return t;
}
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
void ins(int&x,int a,int b,int c,int d,double e){
if(!x)x=++tot;
v[x]+=d,s[x]+=e;
if(a==b)return;
int mid=(a+b)>>1;
if(c<=mid)ins(l[x],a,mid,c,d,e);else ins(r[x],mid+1,b,c,d,e);
}
inline void up(int x){
v[x]=v[l[x]]+v[r[x]];
s[x]=s[l[x]]+s[r[x]];
}
void del(int x,int a,int b,int c,int d){
if(!v[x])return;
if(a==b){
cnt+=v[x],v[x]=0,s[x]=0;
return;
}
int mid=(a+b)>>1;
if(c<=mid)del(l[x],a,mid,c,d);
if(d>mid)del(r[x],mid+1,b,c,d);
up(x);
}
int merge(int x,int y,int a,int b){
if(!x)return y;
if(!y)return x;
if(a==b){
v[x]+=v[y];
s[x]+=s[y];
return x;
}
int mid=(a+b)>>1;
l[x]=merge(l[x],l[y],a,mid);
r[x]=merge(r[x],r[y],mid+1,b);
return up(x),x;
}
inline int kth(int x,int k){
int a=1,b=U,mid;
while(a<b){
mid=(a+b)>>1;
if(v[l[x]]>=k)b=mid,x=l[x];else k-=v[l[x]],a=mid+1,x=r[x];
}
return a;
}
int main(){
read(m);
for(i=1;i<=m;i++){
read(op[i][0]),read(op[i][1]);
if(op[i][0]>1&&op[i][0]<7)read(op[i][2]);
if(op[i][0]==1)b[++U]=op[i][1];
if(op[i][0]==3||op[i][0]==4)b[++U]=op[i][2];
}
sort(b+1,b+U+1);
for(i=1;i<=U;i++)L[i]=log(b[i]);
for(i=1;i<=m;i++){
x=op[i][1],y=op[i][2];
if(op[i][0]==1){
x=lower(x),n++;
f[n]=n,ins(T[n],1,U,x,1,L[x]);
}
if(op[i][0]==2){
x=F(x),y=F(y);
if(x==y)continue;
T[f[x]=y]=merge(T[x],T[y],1,U);
}
if(op[i][0]==3){
x=F(x),y=lower(y),cnt=0;
if(y>1)del(T[x],1,U,1,y-1);
if(cnt)ins(T[x],1,U,y,cnt,L[y]*cnt);
}
if(op[i][0]==4){
x=F(x),y=lower(y),cnt=0;
if(y<U)del(T[x],1,U,y+1,U);
if(cnt)ins(T[x],1,U,y,cnt,L[y]*cnt);
}
if(op[i][0]==5)printf("%d\n",b[kth(T[F(x)],y)]);
if(op[i][0]==6)puts(s[T[F(x)]]>s[T[F(y)]]?"1":"0");
if(op[i][0]==7)printf("%d\n",v[T[F(x)]]);
}
return 0;
}

  

BZOJ4399 : 魔法少女LJJ的更多相关文章

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

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

  2. BZOJ4399 魔法少女LJJ【线段树合并】【并查集】

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

  3. BZOJ4399 魔法少女LJJ(线段树合并)

    注意到只有增加点/合并的操作.这些操作都可以用线段树完成,于是线段树合并一发就好了.注意乘积大小直接比较肯定会炸,取个对数即可.数据中存在重边. #include<iostream> #i ...

  4. 2019.01.16 bzoj4399: 魔法少女LJJ(线段树合并)

    传送门 线段树合并菜题(然而findfindfind函数写错位置调了好久) 支持的操作题目写的很清楚了,然后有一个神奇的限制c≤7c\le7c≤7要注意到不然会去想毒瘤线段树的做法. 思路: 这题只有 ...

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

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

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

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

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

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

  8. 【bzoj4399】魔法少女LJJ 并查集+权值线段树合并

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

  9. bzoj 4399 魔法少女LJJ

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

随机推荐

  1. [BZOJ2502]清理雪道

    [BZOJ2502]清理雪道 试题描述 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定 ...

  2. Insertion Sort List

    对链表进行插入排序,比对数组排序麻烦一点. ListNode *insertSortList(ListNode *head) { ListNode dummy(-); for (ListNode *c ...

  3. 暑假热身 A. GCC

    GCC编译器是一个由GNU项目维护的编译系统,它支持多种编程语言的编译.但是它并不包含数学运算符“!”.在数学中,这个符号代表阶乘.表达式n!的意思是从1到n的所有整数的乘积. 例如,4!=4*3*2 ...

  4. Linux netstat详解

    做计算机管理员,我们都必要了解一下netstat这个命令,它是一个查看网络连接状态的工具,在windows下也默认有这个工具.Netstat命令详解 netstat命令怎样使用 如何关闭TIME_WA ...

  5. 基础知识《五》---Java多线程的常见陷阱

    1.在构造函数中启动线程 我在很多代码中都看到这样的问题,在构造函数中启动一个线程,类似这样: public class A{ public A(){ this.x=1; this.y=2; this ...

  6. hdu5832 A water problem

    A water problem Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  7. poj 1007 DNA Sorting 解题报告

    题目链接:http://poj.org/problem?id=1007 本题属于字符串排序问题.思路很简单,把每行的字符串和该行字符串统计出的字母逆序的总和看成一个结构体.最后把全部行按照这个总和从小 ...

  8. 【数据结构】Huffman树

    参照书上写的Huffman树的代码 结构用的是线性存储的结构 不是二叉链表 里面要用到查找最小和第二小 理论上锦标赛法比较好 但是实现好麻烦啊 考虑到数据量不是很大 就直接用比较笨的先找最小 去掉最小 ...

  9. HDU 1521 排列组合 指数型母函数

    排列组合 Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status D ...

  10. HDU 2.1.7 (求定积分公式)

    The area Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...