二分 WA16 除以0真的不知道怎么改了
查看原帖
二分 WA16 除以0真的不知道怎么改了
353976
Yuzu_Soft楼主2023/5/6 21:37
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,ch[1000005][2],size[1000005],cnt[1000005],f[1000005],key[1000005],sz,root,sum[1000005],mi[1000005],ma[1000005];
int get(int x)
{
	return ch[f[x]][1]==x;
}
void clear(int x)
{
	ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=sum[x]=0;
	mi[x]=1e9;
	ma[x]=-1e9;
}
void update(int x)
{
	if(x)
	{
		size[x]=cnt[x];
		sum[x]=cnt[x]*key[x];
		mi[x]=key[x];
		ma[x]=key[x];
		if(ch[x][0])size[x]+=size[ch[x][0]],sum[x]+=sum[ch[x][0]],mi[x]=min(mi[x],mi[ch[x][0]]),ma[x]=max(ma[x],ma[ch[x][0]]);
		if(ch[x][1])size[x]+=size[ch[x][1]],sum[x]+=sum[ch[x][1]],mi[x]=min(mi[x],mi[ch[x][1]]),ma[x]=max(ma[x],ma[ch[x][1]]);
	}
}
void rotate(int x)
{
	int fa=f[x],fafa=f[fa],k=get(x);
	ch[fa][k]=ch[x][k^1],f[ch[fa][k]]=fa,ch[x][k^1]=fa;
	f[fa]=x,f[x]=fafa;
	if(fafa)ch[fafa][ch[fafa][1]==fa]=x;
	update(fa);
	update(x);
}
void splay(int x,int to=0)
{
	for(int fa;(fa=f[x])!=to;rotate(x))
		if(f[fa]!=to)
			rotate((get(x)==get(fa))?fa:x);
	if(to==0)root=x;
}
void insert(int x)
{
	if(root==0)
	{
		sz++;
		ch[sz][0]=ch[sz][1]=f[sz]=0;
		ma[sz]=mi[sz]=key[sz]=x,cnt[sz]=1;
		sum[sz]=x;
		size[sz]=1;
		root=sz;
		return;
	}
	int now=root,fa=0;
	while(1)
	{
		if(key[now]==x)
		{
			cnt[now]++;
			sum[now]+=x;
			update(now);
			update(fa);
			splay(now);
			break;
		}
		fa=now;
		now=ch[now][key[now]<x];
		if(!now)
		{
			sz++;
			ch[sz][0]=ch[sz][1]=0;
			f[sz]=fa;
			ma[sz]=mi[sz]=key[sz]=x,cnt[sz]=1;
			sum[sz]=x;
			size[sz]=1;
			ch[fa][key[fa]<x]=sz;
			update(fa);
			splay(sz);
			break;
		}
	}
}
int find(int x)
{
	int ret=0,now=root;
	while(1)
		if(key[now]>x)now=ch[now][0];
		else
		{
			ret+=(ch[now][0]?size[ch[now][0]]:0);
			if(x==key[now])
			{
				splay(now);
				return ret+1;
			}
			ret+=cnt[now];
			now=ch[now][1];
		}
}
int findx(int x)
{
	int now=root;
	while(1)
		if(ch[now][0]&&x<=size[ch[now][0]])now=ch[now][0];
		else
		{
			int tmp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
			if(x<=tmp)return key[now];
			x-=tmp;
			now=ch[now][1];
		}
}
int pre()
{
	int now=ch[root][0];
	while(ch[now][1])now=ch[now][1];
	return now;
}
int suffix()
{
	int now=ch[root][1];
	while(ch[now][0])now=ch[now][0];
	return now;
}
void del(int x)
{
	find(x);
	if(cnt[root]>1)
	{
		cnt[root]--;
		sum[root]-=key[root];
		update(root);
		return;
	}
	if(!ch[root][0]&&!ch[root][1])
	{
		clear(root);
		root=0;
		return;
	}
	if(!ch[root][0])
	{
		int t=root;
		root=ch[root][1];
		f[root]=0;
		clear(t);
		return;
	}
	if(!ch[root][1])
	{
		int t=root;
		root=ch[root][0];
		f[root]=0;
		clear(t);
		return;
	}
	int pr=pre(),t=root;
	splay(pr);
	ch[root][1]=ch[t][1];
	f[ch[t][1]]=root;
	clear(t);
	update(root);
}
int a[100005];
signed main()
{
	scanf("%lld%lld",&n,&q);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]),insert(a[i]);
	for(int x,y,opt;q--;)
	{
		scanf("%lld%lld",&opt,&x);
		if(opt==1)
		{
			scanf("%lld",&y);
			del(a[x]);
			a[x]=y;
			insert(a[x]);
		}
		else
		{
			int l=mi[root],r=ma[root],mid,siii,suuu,ans=0;
//			printf("l:%d r:%d\n",l,r);
			while(l<=r)
			{
				mid=l+r>>1;
				insert(mid);
				int su=sum[ch[root][0]],si=size[ch[root][0]];
				siii=size[ch[root][0]]+cnt[root]-1;
				del(mid);
				int k=si*mid-su;
//				printf("ll:%d rr:%d k:%d si:%d su:%d\n",l,r,k,si,su);
				if(k<=x)
				{
					ans=mid;
					l=mid+1;
				}
				if(k>x)r=mid-1;
			}
//			printf("ans:%d ",ans);
			l=ans;
			insert(l);
			siii=size[ch[root][0]]+cnt[root]-1;
			suuu=sum[ch[root][0]]+key[root]*(cnt[root]-1);
			del(l);
			printf("%.5lf\n",1.0*(x+suuu)/siii);
		}
	}
	return 0;
}
//pid:106797704

rt,二分寻找最大可以达到的试管,除以零不会找反例

2023/5/6 21:37
加载中...