BZOJ 4399: 魔法少女LJJ
仔细读题发现c<=7 线段树合并 要比较x和y的大小,比较log(x)和log(y),并查集维护从属关系
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; int cnt,Cnt_sum,num,cas[400005],a[400005],ls[4000005],rs[4000005],sz[4000005],root[400005],X[400005],Y[400005],F[400005]; long double Cnt_log,Log[4000005],tree_log[4000005]; int merge(int x,int y,int l,int r){ if (!x || !sz[x]) return y; if (!y || !sz[y]) return x; sz[x]+=sz[y],tree_log[x]+=tree_log[y]; int mid=(l+r)>>1; ls[x]=merge(ls[x],ls[y],l,mid); rs[x]=merge(rs[x],rs[y],mid+1,r); return x; } int find(int x){ if (x!=F[x]) F[x]=find(F[x]); return F[x]; } void push_down(int x){ sz[ls[x]]=sz[rs[x]]=0; tree_log[ls[x]]=tree_log[rs[x]]=0; } void update(int t){ sz[t]=sz[ls[t]]+sz[rs[t]]; tree_log[t]=tree_log[ls[t]]+tree_log[rs[t]]; } void insert(int &t,int l,int r,int x,int S,long double y){ if (!t) t=++num; if (l==r){ sz[t]+=S,tree_log[t]+=y; return; } if (!sz[t]) push_down(t); int mid=(l+r)>>1; if (x<=mid) insert(ls[t],l,mid,x,S,y); else insert(rs[t],mid+1,r,x,S,y); update(t); } void query(int t,int l,int r,int x,int y){ if (!t) return; if (r<x || l>y) return; if (l>=x && r<=y){ Cnt_sum+=sz[t]; sz[t]=tree_log[t]=0; return; } if (!sz[t]) push_down(t); int mid=(l+r)>>1; query(ls[t],l,mid,x,y); query(rs[t],mid+1,r,x,y); update(t); } int query_K(int x,int l,int r,int K){ int now=root[x]; while (l<r){ int mid=(l+r)>>1; if (!sz[now]) push_down(now); if (sz[ls[now]]>=K) now=ls[now],r=mid; else l=mid+1,K-=sz[ls[now]],now=rs[now]; } return l; } int main(){ int m; scanf("%d",&m); for (int i=1; i<=m; i++){ scanf("%d",&cas[i]); scanf("%d",&X[i]); if (cas[i]==2 || cas[i]==3 || cas[i]==4 || cas[i]==5 || cas[i]==6) scanf("%d",&Y[i]); if (cas[i]==1) a[++cnt]=X[i]; if (cas[i]==3 || cas[i]==4) a[++cnt]=Y[i]; } sort(a+1,a+cnt+1); cnt=unique(a+1,a+cnt+1)-a-1; for (int i=1; i<=m; i++){ if (cas[i]==1) Log[i]=log((double)X[i]),X[i]=lower_bound(a+1,a+cnt+1,X[i])-a; if (cas[i]==3 || cas[i]==4) Log[i]=log((double)Y[i]),Y[i]=lower_bound(a+1,a+cnt+1,Y[i])-a; } // for (int i=1; i<=m; i++) // if (cas[i]==1 || cas[i]==3 || cas[i]==4) printf("%lf ",Log[i]); // printf("\n"); int S=0; for (int i=1; i<=m; i++) if (cas[i]==1){ S++; F[S]=S; insert(root[S],1,cnt,X[i],1,Log[i]); } else if (cas[i]==2){ int x=find(X[i]),y=find(Y[i]); if (x==y) continue; F[y]=x; root[x]=merge(root[x],root[y],1,cnt); } else if (cas[i]==3){ int x=find(X[i]); Cnt_sum=Cnt_log=0; query(root[x],1,cnt,1,Y[i]); insert(root[x],1,cnt,Y[i],Cnt_sum,Log[i]*Cnt_sum); } else if (cas[i]==4){ int x=find(X[i]); Cnt_sum=Cnt_log=0; query(root[x],1,cnt,Y[i],cnt); insert(root[x],1,cnt,Y[i],Cnt_sum,Log[i]*Cnt_sum); } else if (cas[i]==5){ int x=find(X[i]); int K=query_K(x,1,cnt,Y[i]); printf("%d\n",a[K]); } else if (cas[i]==6){ int x=find(X[i]),y=find(Y[i]); long double cnt_x=tree_log[root[x]]; long double cnt_y=tree_log[root[y]]; if (cnt_x>cnt_y) printf("1\n"); else printf("0\n"); } else if (cas[i]==7){ int x=find(X[i]); printf("%d\n",sz[root[x]]); } return 0; }