Why Did the Cow Cross the Road III HYSBZ - 4991 -CDQ-逆序数

  • HYSBZ - 4991
  • 题意: 第一列 1-n的排列 ,第二列 1-n的排列。  相同数字连边  ,问  有多少组 数字 是有交点的并且 绝对值之差>K
    思路:处理一下 1-n 在第一列的位置,1-n在第二列的位置。按照第一列的位置从小到大排序,然后 进行cdq分治,
    因为现在第一列已经是递增序列了,如果在第二列中出现了递减那么这两个数就有交点,分治解决,递归左区间 
    的必然第一列必然小于递归右区间。所以只处理左区间对右区间的影响,两段小区间分别按照 b 从大到小排序,
    然后 统计 左区间的b  比右区间大的树状数组更新那个数字。然后更新完成之后查询, 右区间当前的数
    (绝对值之差>K无非就是, < x-k  有多少 ,  > x+k有多少)分别 树状数组进行查询,进行完成之后 ,
    数组数组恢复最初状态,回溯 继续处理大区间即可
  • #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define maxn 100010
    struct node
    {
        int num,a,b;
    } data[maxn];
    bool cp(node x,node y)
    {
        return x.a<y.a;
    };
    bool cp2(node x,node y)
    {
        return x.b>y.b;
    };
    int tree[maxn],n,k,x;
    ll ans;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int x,int ad)
    {
        while(x<=n)
        {
            tree[x]+=ad;
            x+=lowbit(x);
        }
    }
    int query(int x)
    {
        int re=0;
        while(x>0)
        {
            re+=tree[x];
            x-=lowbit(x);
        }
        return re;
    }
    void cdq(int l,int r)
    {
        if(l==r)return ;
        int mid=(l+r)>>1;
        cdq(l,mid);
        cdq(mid+1,r);
        sort(data+l,data+1+mid,cp2);
        sort(data+mid+1,data+1+r,cp2);
        int i=l,j=mid+1;
        for(; j<=r; j++)
        {
            while(data[i].b>data[j].b&&i<=mid)
            {
                add(data[i].num,1);
                i++;
            }
            ans+=query(data[j].num-k-1);
            if(data[j].num+k<n)ans+=query(n)-query(data[j].num+k);
        }
        for(j=l; j<i; j++)
            add(data[j].num,-1);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            data[i].num=i;
            data[x].a=i;
        }
        for(int j=1; j<=n; j++)
        {
            scanf("%d",&x);
            data[x].b=j;
        }
        sort(data+1,data+1+n,cp);
        cdq(1,n);
        printf("%lld\n",ans);
        return 0;
    }
    

      

原文地址:https://www.cnblogs.com/SDUTNING/p/10261631.html

时间: 2024-10-04 15:33:46

Why Did the Cow Cross the Road III HYSBZ - 4991 -CDQ-逆序数的相关文章

[USACO17FEB]Why Did the Cow Cross the Road III P(CDQ分治)

题意 两列$n$的排列,相同的数连边,如果一对数有交叉且差的绝对值$>k$,则$++ans$,求$ans$ 题解 可以把每一个数字看成一个三元组$(x,y,z)$,其中$x$表示在第一列的位置,$y$表示在第二列的位置,$z$表示权值 两条线交叉,就是$x<x'$且$y>y'$,又要满足差值的绝对值小于等于$k$,就是$|z-z'|<=k$ 于是就转化为了一个三维偏序问题,直接上CDQ 具体细节请看代码 1 // luogu-judger-enable-o2 2 //minamot

Why Did the Cow Cross the Road III(树状数组)

Why Did the Cow Cross the Road III 时间限制: 1 Sec  内存限制: 128 MB提交: 65  解决: 28[提交][状态][讨论版] 题目描述 The layout of Farmer John's farm is quite peculiar, with a large circular road running around the perimeter of the main field on which his cows graze during

洛谷 P3660 [USACO17FEB]Why Did the Cow Cross the Road III G(树状数组)

题目背景 给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数 题目描述 The layout of Farmer John's farm is quite peculiar, with a large circular road running around the perimeter of the main field on which his cows graze during the day. Every morn

BZOJ4994 [Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4994 题意概括 给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数. n<=100000(这个数据范围是我凑出来的,但是我没试过更小的范围,BZOJ上没写数据范围(截止2017-08-24)) 题解 水题,开一个树状数组在线解决. 比如我们顺着扫过去,当到达一个 bj 时,我们求满足条件的 ai,bi 个数,其实就

[BZOJ4994] [Usaco2017 Feb]Why Did the Cow Cross the Road III(树状数组)

传送门 1.每个数的左右位置预处理出来,按照左端点排序,因为左端点是从小到大的,我们只需要知道每条线段包含了多少个前面线段的右端点即可,可以用树状数组 2.如果 ai < bj < bi, 也就是说在两个i之间只有一个j那么对答案的贡献为1,所以可以用树状数组,当第一次出现一个数的时候,那个位置+1,当第二次出现的时候,第一次出现的位置再-1,也就是把它对答案的贡献去掉,同样是树状数组统计答案 #include <cstdio> #include <iostream>

【bzoj4994】[Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组

题目描述 给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数 样例输入 4 3 2 4 4 1 3 2 1 样例输出 3 题解 树状数组 WH说是CDQ分治直接把我整蒙了... 把所有数按照第一次出现位置从小到大排序,然后扫一遍.此时一定是满足$a_j>a_i$的. 那么只需要求出$(a_j,b_j)$中以前出现过的$b_i$的数目.使用树状数组维护即可. 时间复杂度$O(n\log n)$ #include &l

洛谷 P3662 [USACO17FEB]Why Did the Cow Cross the Road II S

P3662 [USACO17FEB]Why Did the Cow Cross the Road II S 题目描述 The long road through Farmer John's farm has NN crosswalks across it, conveniently numbered 1 \ldots N1…N (1 \leq N \leq 100,0001≤N≤100,000). To allow cows to cross at these crosswalks, FJ in

BZOJ4989 [Usaco2017 Feb]Why Did the Cow Cross the Road 树状数组 逆序对

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4989 题意概括 一条马路的两边分别对应的序列A.B,长度为n,两序列为1到n的全排列.当Ai=Bj时,两边之间会连一条边.你可以选择序列A或序列B进行旋转(只能使队尾或队头位置上的数字变成队头或队尾上的数字)任意K(0<=K<n)步,如123,可以变成 231 或 312.求旋转后,最少的边的交叉数. 题解 两个都可以转,那么我们只需要分别转动两个并统计即可. 旋转一个,那么我们只需要统计逆序

[BZOJ4989] [Usaco2017 Feb]Why Did the Cow Cross the Road(树状数组)

传送门 发现就是逆序对 可以树状数组求出 对于旋转操作,把一个序列最后面一个数移到开头,假设另一个序列的这个数在位置x,那么对答案的贡献 - (n - x) + (x - 1) #include <cstdio> #include <cstring> #include <iostream> #define N 200011 #define LL long long using namespace std; int n; int a[N], b[N], pos1[N],