【XSY2714】大佬的难题 数学 树状数组

题目描述

  给你三个排列\(A,B,C\),求
\[
\sum_{1\leq x,y\leq n}[a_x<a_y][b_x<b_y][c_x<c_y]
\]
  \(n\leq 2\times {10}^6\)

题解

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

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

  我们记
\[
\begin{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_{1\leq x\leq y\leq n}[S_{x,y}=3]\B&=\sum_{1\leq x\leq y\leq n}[S_{x,y}=2]\P_{a,b}&=\sum_{1\leq x,y\leq n}[a_x<a_y][b_x<b_y]\P_{a,c}&=\sum_{1\leq x,y\leq n}[a_x<a_y][c_x<c_y]\P_{b,c}&=\sum_{1\leq x,y\leq n}[b_x<b_y][c_x<c_y]\\end{align}
\]
  那么我们要求的答案就是\(A\)了。

  容易发现
\[
\begin{align}
A+B&=\binom{n}{2}\3A+B&=P_{a,b}+P_{a,c}+P_{b,c}
\end{align}
\]
  原问题转化为二位偏序。

  用树状数组即可解决。

  时间复杂度:\(O(n\log 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\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/ywwyww/p/8513559.html

时间: 2024-10-01 09:29:51

【XSY2714】大佬的难题 数学 树状数组的相关文章

[CSP-S模拟测试]:Equation(数学+树状数组)

题目描述 有一棵$n$个点的以$1$为根的树,以及$n$个整数变量$x_i$.树上$i$的父亲是$f_i$,每条边$(i,f_i)$有一个权值$w_i$,表示一个方程$x_i+x_{f_i}=w_i$,这$n−1$个方程构成了一个方程组.现在给出$q$个操作,有两种类型:$\bullet 1\ u\ v\ s$,表示询问加上$x_u+x_v=s$这个方程后,整个方程组的解的情况.具体来说,如果方程有唯一解,输出此时$x_1$的值:如果有无限多个解,输出$inf$:如果无解,输出$none$.注意

[CSP-S模拟测试]:天才绅士少女助手克里斯蒂娜(数学+树状数组)

题目描述 红莉栖想要弄清楚楼下天王寺大叔的显像管电视对“电话微波炉(暂定)”的影响. 选取显像管的任意一个平面,一开始平面内有个$n$电子,初始速度分别为$v_i$,定义飘升系数为$$\sum \limits_{1\leqslant i<j\leqslant n}|v_i\times v_j|^2$$ 由于电视会遭到大叔不同程度的暴击,电子的速度常常会发生变化.也就是说,有两种类型的操作: $\bullet 1\ p\ x\ y$将$v_p$改为$(x,y)$ $\bullet 2\ l\ r$

HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景

http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, R]中不同区间的gcd值,有多少个是不同的. 给个样例 3 37 7 71 21 33 3 数学背景: 一个数字和若N个数字不断GCD,其结果只有loga[i]种,为什么呢?因为可以把a[i]质因数分解,其数目最多是loga[i]个数字相乘.(最小的数字是2,那么loga[i]个2相乘也爆了a[i]

[CF808B] Average Sleep Time([强行]树状数组,数学)

题目链接:http://codeforces.com/contest/808/problem/B 题意:n个数,求其中每k个数的和的平均值. 鬼知道我怎么会石乐志上来就用了树状数组. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 200200; 6 int n, k; 7 LL a[maxn], bit[maxn]; 8 int lowbit(int

Codeforces Round #470 (Div 2) B 数学 C 二分+树状数组 D 字典树

Codeforces Round #470 B. Primal Sport 数学题,对 x2 和 x1 分解质因子即可. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b;

Master of Sequence(数学+二分+树状数组)

题意:给两个长度为n的序列(a1,a2......,an).(b1,b2......bn)和m个询问以及一个整数k,找出满足k <= S(t) = Σ(i=1 to n) ((t-bi) / ai)向下取整  的最小t.考虑函数的单调性此题可以二分,对于该式子可以证明 ((t-bi) / ai)向下取整的值就是 (t/ai)向下取整的值减去 (bi/ai)向下取整的值 如果 (t%ai) - (bi%ai) 的值比0小,说明还得到前面算出来的(t/ai)的值那里拿一个1来减, 所以算出来的值应该

吊打线段树的超级树状数组

你是否讨厌线段树那冗长的代码?你是否还在因为线段树的难调试而满头♂dark汗?那么,请不要错过!超级树状数组特价!只要998,只要998! ##¥……#……¥%……&%¥……ER#%$#$#^T%$^$% 超级树状数组,其实是一种能够支持区间修改和区间查询的树状数组,和线段树相比,它的常数极小,不需要太多空间,代码量也少了很多(简直吊打线段树) 1.树状数组 既然是超级树状数组,那么就需要一个树状数组作为基础了.但是在真正实现时,只用到了lowbit()函数(所以说lowbit是树状数组的核心啊

浅析树状数组(二叉索引树)及一些模板

树状数组 动态连续和查询问题.给定一个n个元素的数组a1.a2.……,an,设计一个数据结构,支持以下两种操作:1.add(x,d):让ax增加d;2.query(l,r):计算al+al+1+…+ar 如何让query和add都能快速完成呢?方法有很多,这里介绍的便是树状数组.为此我们先介绍lowbit. 对于正整数x,我们定义lowbit(x)为x的二进制表达式中最右边的1所对应的值(而不是这个比特的序号).比如,38288的二进制1001010110010000,所以lowbit(3828

树状数组

树状数组                   转自:      By 岩之痕  http://blog.csdn.net/zearot/article/details/45028723 一.概述 树状数组是一种 用数组进行存储的 自下而上进行操作的  多叉树. 以下叙述中,A为原数组,C为树状数组所用的数组,B为特殊情况需要用到的辅助数组. 最基本的应用就是维护一个支持两种操作的数列:1.让A[i]加上某数X     2.求一个区间A[L] + A[L+1] + ... + A[R] 的和. 树