魔法少女 LJJ——线段树
题目
【题目描述】
在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女 LJJ 已经觉得自己见过世界上的所有稀奇古怪的事情了。
LJJ 感叹道“这里真是个迷人的绿色世界,空气清新、淡雅,到处散发着醉人的奶浆味;小猴在枝头悠来荡去,好不自在;各式各样的鲜花争相开放,各种树枝的枝头挂满沉甸甸的野果;鸟儿的歌声婉转动听,小河里飘着落下的花瓣真是人间仙境”。
SHY 觉得 LJJ 还是太 naive,一天, SHY 带着自己心爱的图找到 LJJ,对 LJJ 说:“既然你已经见识过动态树,动态仙人掌了,那么今天就来见识一下动态图吧”。
LJJ:“要支持什么操作?”
SHY:
1. 新建一个节点,权值为 $x$。
2. 连接两个节点。
3. 将一个节点 $a$ 所属于的联通快内权值小于 $x$ 的所有节点权值变成 $x$。
4. 将一个节点 $a$ 所属于的联通快内权值大于 $x$ 的所有节点权值变成 $x$。
5. 询问一个节点 $a$ 所属于的联通块内的第 $k$ 小的权值是多少。
6. 询问一个节点 $a$ 所属联通快内所有节点权值之积与另一个节点 $b$ 所属联通快内所有节点权值之积的大小。
7. 询问 $a$ 所在联通块内节点的数量
8. 若两个节点 $a$,$b$ 直接相连,将这条边断开。
9. 若节点 $a$ 存在,将这个点删去。
LJJ:“我可以离线吗?”
SHY:“可以,每次操作是不加密的。”
LJJ:“我可以暴力吗?”
SHY:“自重。”
LJJ很郁闷,你能帮帮他吗?
【输入格式】
第一行一个整数 $n$ ,代表岛屿数量。
接下来 $n-1$ 行,每行三个整数 $u,v,w$ ,代表 $u$ 号岛屿和 $v$ 号岛屿由一条代价为 $c$ 的桥梁直接相连,保证 $1 \le u,v \le n$ 且 $1 \le c \le 100000 $ 。
第 $n+1$ 行,一个整数 $m$ ,代表敌方机器能使用的次数。
接下来 $m$ 行,每行一个整数 $k_i$ ,代表第 $i$ 次后,有 $k_i$ 个岛屿资源丰富,接下来 $k$ 个整数$h_1,h_2,…h_k$ ,表示资源丰富岛屿的编号。
【输出格式】
具体输出格式见样例 。
【样例输入】
12
1 2
1 3
1 4
1 5
1 6
2 1 2
2 2 3
2 3 4
2 4 5
9 1
3 2 5
5 3 4
【样例输出】
6
【数据范围与提示】
对 $100\%$ 的数据 $0\le m \le 400000,c \le 7$,所有出现的数均 $\le 1000000000$,所有出现的点保证存在.
题解
题目中 $ c \leq 7 $,即说明仅有前 $ 7 $ 个操作
对于操作一,新建一棵线段树,并插入这个点的值
对于操作二,合并两颗线段树,用并查集维护
对于操作三,查询个数并删除小于 $ x $ 的点,插入 $ x $
对于操作四,类似三
对于操作五,线段树上二分即可
对于操作六,可以发现 $ \log(a\times b)=\log a+\log b $,所以转化成 $ log x $ 比较和即可
对于操作七,查询整个线段树点的个数即可
于是这又是一道大力题
代码
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define db double 4 #define _(d) while(d(isdigit(ch=getchar()))) 5 using namespace std; 6 int R(){ 7 int x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48; 8 _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;} 9 const int N=2e6+5; 10 int n,m,tmp,cnt,fa[N],d[N],rot[N]; 11 struct node{int op,x,y;}q[N]; 12 struct seg{int ls,rs,num;bool tag;db val;}tr[N*20]; 13 int ef(int x){return lower_bound(d+1,d+1+n,x)-d;} 14 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 15 #define Ls(x) tr[x].ls 16 #define Rs(x) tr[x].rs 17 void pushup(int rt){ 18 tr[rt].num=tr[Ls(rt)].num+tr[Rs(rt)].num; 19 tr[rt].val=tr[Ls(rt)].val+tr[Rs(rt)].val; 20 return; 21 } 22 void pushdown(int rt){ 23 tr[rt].tag=0; 24 tr[Ls(rt)].num=tr[Ls(rt)].val=0,tr[Ls(rt)].tag=1; 25 tr[Rs(rt)].num=tr[Rs(rt)].val=0,tr[Rs(rt)].tag=1; 26 return; 27 } 28 void insert(int &rt,int l,int r,int k,int x,db y){ 29 if(!rt)rt=++cnt; 30 if(l==r){tr[rt].num+=x,tr[rt].val+=y;return;} 31 int mid=(l+r)>>1; 32 if(tr[rt].tag)pushdown(rt); 33 if(k<=mid)insert(Ls(rt),l,mid,k,x,y); 34 else insert(Rs(rt),mid+1,r,k,x,y); 35 pushup(rt); 36 return; 37 } 38 void merge(int &o1,int o2,int l,int r){ 39 if(!o1||!o2){o1+=o2;return;} 40 if(l==r){ 41 tr[o1].num+=tr[o2].num,tr[o1].val+=tr[o2].val; 42 return; 43 } 44 int mid=(l+r)>>1; 45 if(tr[o1].tag)pushdown(o1); 46 if(tr[o2].tag)pushdown(o2); 47 merge(Ls(o1),Ls(o2),l,mid),merge(Rs(o1),Rs(o2),mid+1,r); 48 pushup(o1); 49 return; 50 } 51 int query(int rt,int l,int r,int ql,int qr){ 52 if(!rt||qr<ql)return 0; 53 if(ql<=l&&qr>=r)return tr[rt].num; 54 int mid=(l+r)>>1,res=0; 55 if(tr[rt].tag)pushdown(rt); 56 if(ql<=mid)res=query(Ls(rt),l,mid,ql,qr); 57 if(qr>mid)res+=query(Rs(rt),mid+1,r,ql,qr); 58 return res; 59 } 60 void clean(int rt,int l,int r,int ql,int qr){ 61 if(!rt||qr<ql)return; 62 if(ql<=l&&qr>=r){ 63 tr[rt].num=tr[rt].val=0,tr[rt].tag=1; 64 return; 65 } 66 int mid=(l+r)>>1; 67 if(ql<=mid)clean(Ls(rt),l,mid,ql,qr); 68 if(qr>mid)clean(Rs(rt),mid+1,r,ql,qr); 69 pushup(rt); 70 return; 71 } 72 int ask(int rt,int l,int r,int k){ 73 if(l==r)return d[l]; 74 int mid=(l+r)>>1; 75 if(tr[rt].tag)pushdown(rt); 76 if(k<=tr[Ls(rt)].num)return ask(Ls(rt),l,mid,k); 77 else return ask(Rs(rt),mid+1,r,k-tr[Ls(rt)].num); 78 } 79 int main(){ 80 m=R(); 81 for(int i=1;i<=m;i++){ 82 int op=R(),x=R(),y=0; 83 if(op!=1&&op!=7)y=R(); 84 q[i]=(node){op,x,y}; 85 if(op==3||op==4)d[++n]=y; 86 if(op==1)d[++n]=x; 87 } 88 sort(d+1,d+1+n); 89 n=unique(d+1,d+1+n)-d-1; 90 for(int i=1;i<=m;i++){ 91 int op=q[i].op,x=q[i].x,y=q[i].y; 92 if(op==1)insert(rot[++tmp],1,n,ef(x),1,(db)log(x)),fa[tmp]=tmp; 93 if(op==2){ 94 int fx=find(x),fy=find(y); 95 if(fx!=fy)fa[fy]=fx,merge(rot[fx],rot[fy],1,n); 96 } 97 if(op==3){ 98 int fx=find(x),k=ef(y),sum=query(rot[fx],1,n,1,k-1); 99 clean(rot[fx],1,n,1,k-1),insert(rot[fx],1,n,k,sum,sum*log(y)); 100 } 101 if(op==4){ 102 int fx=find(x),k=ef(y),sum=query(rot[fx],1,n,k+1,n); 103 clean(rot[fx],1,n,k+1,n),insert(rot[fx],1,n,k,sum,sum*log(y)); 104 } 105 if(op==5)printf("%d\n",ask(rot[find(x)],1,n,y)); 106 if(op==6)puts(tr[rot[find(x)]].val>tr[rot[find(y)]].val?"1":"0"); 107 if(op==7)printf("%d\n",tr[rot[find(x)]].num); 108 } 109 return 0; 110 }