zoukankan      html  css  js  c++  java
  • 【XSY2714】大佬的难题 数学 树状数组

    题目描述

      给你三个排列(A,B,C),求

    [sum_{1leq x,yleq n}[a_x<a_y][b_x<b_y][c_x<c_y] ]

      (nleq 2 imes {10}^6)

    题解

      就是一个三位偏序。用CDQ分治可以做到(O(nlog^2 n))常熟小一点可以卡过。我在UOJ上面能跑过去。

      这道题只有一个特殊性质:(A,B,C)都是排列。

      我们记

    [egin{align} K_{x,y}&=[a_x<a_y]+[b_x<b_y]+[c_x<c_y]\ S_{x,y}&=max(K_{x,y},K_{y,x})\ A&=sum_{1leq xleq yleq n}[S_{x,y}=3]\ B&=sum_{1leq xleq yleq n}[S_{x,y}=2]\ P_{a,b}&=sum_{1leq x,yleq n}[a_x<a_y][b_x<b_y]\ P_{a,c}&=sum_{1leq x,yleq n}[a_x<a_y][c_x<c_y]\ P_{b,c}&=sum_{1leq x,yleq n}[b_x<b_y][c_x<c_y]\ end{align} ]

      那么我们要求的答案就是(A)了。

      容易发现

    [egin{align} A+B&=inom{n}{2}\ 3A+B&=P_{a,b}+P_{a,c}+P_{b,c} end{align} ]

      原问题转化为二位偏序。

      用树状数组即可解决。

      时间复杂度:(O(nlog n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<utility>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    ll seed;
    ll rd()
    {
    	return seed=((seed*19260817)^233333)&((1<<24)-1);
    }
    int n;
    void gen(int *a)
    {
    	int i;
    	for(i=1;i<=n;i++)
    		a[i]=i;
    	for(i=1;i<=n;i++)
    		swap(a[i],a[rd()%i+1]);
    }
    int a1[2000010];
    int a2[2000010];
    int a3[2000010];
    int a[2000010];
    int c[2000010];
    void add(int x)
    {
    	for(;x<=n;x+=x&-x)
    		c[x]++;
    }
    int sum(int x)
    {
    	int s=0;
    	for(;x;x-=x&-x)
    		s+=c[x];
    	return s;
    }
    ll gao(int *a1,int *a2)
    {
    	memset(c,0,sizeof c);
    	int i;
    	for(i=1;i<=n;i++)
    		a[a1[i]]=a2[i];
    	ll s=0;
    	for(i=1;i<=n;i++)
    	{
    		s+=sum(a[i]);
    		add(a[i]);
    	}
    	return s;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    #endif
    	scanf("%d",&n);
    	scanf("%lld",&seed);
    	gen(a1);
    	scanf("%lld",&seed);
    	gen(a2);
    	scanf("%lld",&seed);
    	gen(a3);
    	ll ans=0;
    	ans+=gao(a1,a2);
    	ans+=gao(a1,a3);
    	ans+=gao(a2,a3);
    	ans-=ll(n-1)*n/2;
    	ans/=2;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    剑指offer-最小的k个数
    剑指offer-数组中出现次数超过一半的数字
    android开发------响应用户事件
    android开发------初识Activity
    android开发------编写用户界面之相对布局
    android开发------编写用户界面之线性布局(补充知识)
    android开发------编写用户界面之线性布局
    android开发------第一个android程序
    加密狗的工作原理
    克隆加密狗、复制加密狗、破解加密狗的定义区别
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513559.html
Copyright © 2011-2022 走看看