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

  

posted @ 2018-10-18 16:13  ~Silent  阅读(201)  评论(0编辑  收藏  举报
Live2D