BZOJ 4399: 魔法少女LJJ(線段樹)
阿新 • • 發佈:2019-02-08
cst bound += truct ref 維護 tmp 線段 class
傳送門
解題思路
出題人真會玩。。操作\(2\)線段樹合並,然後每棵線段樹維護元素個數和。對於\(6\)這個詢問,因為乘積太大,所以要用對數。時間復雜度\(O(nlogn)\)
代碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=400005; const int M=2000005; inline int rd(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) f=ch==‘-‘?0:1,ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar(); return f?x:-x; } int m,tot,rt[M],F[M],num,cpy[N],cnt,a[N],u,tmp; struct Query{ int op,x,y; }q[N]; struct Segment_Tree{ double Mul[M]; int siz[M],ls[M],rs[M]; void update(int &x,int l,int r,int s,int k,double now){ if(!x) x=++tot; siz[x]+=s; Mul[x]+=s*now; if(l==r) return; int mid=(l+r)>>1; if(k<=mid) update(ls[x],l,mid,s,k,now); else update(rs[x],mid+1,r,s,k,now); } int merge(int x,int y,int l,int r){ if(!x || !y) return (x|y); if(l==r) {siz[x]+=siz[y]; Mul[x]+=Mul[y]; return x;} int mid=(l+r)>>1; ls[x]=merge(ls[x],ls[y],l,mid); rs[x]=merge(rs[x],rs[y],mid+1,r); siz[x]=siz[ls[x]]+siz[rs[x]]; Mul[x]=Mul[ls[x]]+Mul[rs[x]]; return x; } void erase(int x,int l,int r,int L,int R){ if(L>R || !siz[x]) return; if(l==r) {tmp+=siz[x]; siz[x]=0; Mul[x]=0; return;} int mid=(l+r)>>1; if(L<=mid) erase(ls[x],l,mid,L,R); if(mid<R) erase(rs[x],mid+1,r,L,R); siz[x]=siz[ls[x]]+siz[rs[x]]; Mul[x]=Mul[ls[x]]+Mul[rs[x]]; } int kth(int x,int l,int r,int k){ if(l==r) return l; int mid=(l+r)>>1; if(siz[ls[x]]>=k) return kth(ls[x],l,mid,k); else {k-=siz[ls[x]]; return kth(rs[x],mid+1,r,k);} } }tree; int get(int x){ if(x==F[x]) return x; return F[x]=get(F[x]); } int main(){ m=rd(); int x,y,uu,vv; for(int i=1;i<=m;i++){ q[i].op=rd(),q[i].x=rd(); if(q[i].op==1) cpy[++cnt]=q[i].x; if(q[i].op==1 || q[i].op==7) continue; q[i].y=rd(); if(q[i].op==3 || q[i].op==4) cpy[++cnt]=q[i].y; } sort(cpy+1,cpy+1+cnt); u=unique(cpy+1,cpy+1+cnt)-cpy-1; for(int i=1;i<=m;i++){ if(q[i].op==1){ x=lower_bound(cpy+1,cpy+1+u,q[i].x)-cpy; num++; F[num]=num; tree.update(rt[num],1,u,1,x,log(q[i].x)); } else if(q[i].op==2){ x=q[i].x,y=q[i].y; uu=get(x),vv=get(y); if(uu==vv) continue; F[vv]=uu; rt[uu]=tree.merge(rt[uu],rt[vv],1,u); } else if(q[i].op==3){ x=q[i].x,y=lower_bound(cpy+1,cpy+1+u,q[i].y)-cpy; tmp=0; x=get(x); tree.erase(rt[x],1,u,1,y-1); if(tmp) tree.update(rt[x],1,u,tmp,y,log(q[i].y)); } else if(q[i].op==4){ x=q[i].x,y=lower_bound(cpy+1,cpy+1+u,q[i].y)-cpy; tmp=0; x=get(x); tree.erase(rt[x],1,u,y+1,u); if(tmp) tree.update(rt[x],1,u,tmp,y,log(q[i].y)); } else if(q[i].op==5){ x=q[i].x; y=q[i].y; x=get(x); printf("%d\n",cpy[tree.kth(rt[x],1,u,y)]); } else if(q[i].op==6) { x=get(q[i].x); y=get(q[i].y); puts(tree.Mul[rt[x]]>tree.Mul[rt[y]]?"1":"0"); } else if(q[i].op==7) printf("%d\n",tree.siz[rt[get(q[i].x)]]); } return 0; }
BZOJ 4399: 魔法少女LJJ(線段樹)