zoukankan      html  css  js  c++  java
  • 【XSY2669】归并排序 树状数组 简单组合数学

    题目描述

      有一个长度为(n)的排列(n=2^k),你要把这个数组归并排序。但是在长度为(2)的时候有(frac{1}{2})的概率会把两个数交换(就是有(frac{1}{2})的概率返回错的结果)。有两种操作

      (1):交换两个数

      (2):询问排序后的一个位置等于一个数的概率。

      (kleq 16,qleq {10}^5)

    题解

      这个排序有点奇怪。两个数(a,b(a<b))排序后可能是(ab)也可能是(ba)

      观察到(ab)会正常排序,而(ba)(a)会一直跟着(b),所以可以把(a)看成(b+0.5)

      这样就会有一些数确定,有些数是两个数中的一个。

      用两个树状数组维护小的数和大的数不超过(x)的个数,每次询问用组合数乱搞即可。

      时间复杂度:(O((n+q)log n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<cmath>
    #include<functional>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> pll;
    void sort(int &a,int &b)
    {
    	if(a>b)
    		swap(a,b);
    }
    void open(const char *s)
    {
    #ifndef ONLINE_JUDGE
    	char str[100];
    	sprintf(str,"%s.in",s);
    	freopen(str,"r",stdin);
    	sprintf(str,"%s.out",s);
    	freopen(str,"w",stdout);
    #endif
    }
    int rd()
    {
    	int s=0,c;
    	while((c=getchar())<'0'||c>'9');
    	do
    	{
    		s=s*10+c-'0';
    	}
    	while((c=getchar())>='0'&&c<='9');
    	return s;
    }
    void put(int x)
    {
    	if(!x)
    	{
    		putchar('0');
    		return;
    	}
    	static int c[20];
    	int t=0;
    	while(x)
    	{
    		c[++t]=x%10;
    		x/=10;
    	}
    	while(t)
    		putchar(c[t--]+'0');
    }
    int upmin(int &a,int b)
    {
    	if(b<a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    int upmax(int &a,int b)
    {
    	if(b>a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    const ll p=1000000007;
    ll fp(ll a,ll b)
    {
    	ll s=1;
    	for(;b;b>>=1,a=a*a%p)
    		if(b&1)
    			s=s*a%p;
    	return s;
    }
    int n,a[100010];
    int c1[200010];
    int c2[200010];
    void add(int *c,int x,int v)
    {
    	for(;x<=2*n;x+=x&-x)
    		c[x]+=v;
    }
    int sum(int *c,int x)
    {
    	int s=0;
    	for(;x;x-=x&-x)
    		s+=c[x];
    	return s;
    }
    int a1[100010];
    int a2[100010];
    int o(int x)
    {
    	return ((x-1)^1)+1;
    }
    void add(int x,int v)
    {
    	int y=o(x);
    	if(a[x]>a[y])
    	{
    		add(c1,2*a[x]-1,v);
    		add(c2,2*a[x]-1,v);
    		a1[x]=a2[x]=2*a[x]-1;
    	}
    	else
    	{
    		add(c1,2*a[x]-1,v);
    		add(c2,2*a[y],v);
    		a1[x]=2*a[x]-1;
    		a2[x]=2*a[y];
    	}
    }
    ll inv[100010];
    ll fac[100010];
    ll ifac[100010];
    ll c(int x,int y)
    {
    	if(x<y)
    		return 0;
    	if(y<0)
    		return 0;
    	return fac[x]*ifac[y]%p*ifac[x-y]%p;
    }
    ll query(int x,int y,int b=0)
    {
    	ll ans=1;
    	x--;
    	y--;
    	int s1=sum(c2,y);
    	int s2=sum(c1,y)-s1;
    	if(b)
    		s2--;
    	ans=ans*c(s2,x-s1)%p*fp(inv[2],s2)%p;
    	return ans;
    }
    int main()
    {
    	open("c");
    	scanf("%d",&n);
    	int i;
    	inv[0]=inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
    	for(i=2;i<=n;i++)
    	{
    		inv[i]=-p/i*inv[p%i]%p;
    		fac[i]=fac[i-1]*i%p;
    		ifac[i]=ifac[i-1]*inv[i]%p;
    	}
    	for(i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	for(i=1;i<=n;i++)
    		add(i,1);
    	int q;
    	scanf("%d",&q);
    	int op,x,y;
    	for(i=1;i<=q;i++)
    	{
    		scanf("%d%d%d",&op,&x,&y);
    		if(op==1)
    		{
    			add(x,-1);
    			add(y,-1);
    			add(o(x),-1);
    			add(o(y),-1);
    			swap(a[x],a[y]);
    			add(x,1);
    			add(y,1);
    			add(o(x),1);
    			add(o(y),1);
    		}
    		else
    		{
    			ll ans;
    			if(a1[x]==a2[x])
    				ans=query(y,a1[x]);
    			else
    				ans=(query(y,a1[x])+query(y,a2[x],1))*inv[2]%p;
    			ans=(ans+p)%p;
    			printf("%lld
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    JavaScript操作服务器控件之Gridview控件
    GridView_RowDataBound 常用方法
    GridView ,后台修改 跟新完毕,前端 未跟新处理
    怎么判断DropDownList是否选择值
    GridView.SelectedIndex
    DropDownlist数据SelectedIndexChanged触发问题解决
    error:将字符串转换为 uniqueidentifier 时失败
    UniqueIdentifier 数据类型
    在Sql2005中,向表中插入数据时遇到uniqueidentifier列,如何插入数据?
    mysql给id生成uuid
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513605.html
Copyright © 2011-2022 走看看