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;
}

浙公网安备 33010602011771号