BZOJ 4919 [Usaco2017 Feb]Why Did the Cow Cross the Road III(cdq分治)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baodream/article/details/82695718

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4991

Description

Farmer John is continuing to ponder the issue of cows crossing the road through his farm, introduced

 in the preceding two problems. He realizes now that the threshold for friendliness is a bit more su

btle than he previously considered -- breeds aa and bb are now friendly if |a-b|≤K, and unfriendly 

otherwise.Given the orderings of fields on either side of the road through FJ's farm, please count t

he number of unfriendly crossing pairs of breeds, where a crossing pair of breeds is defined as in t

he preceding problems.

思考过前两个问题后,农民约翰正在继续思考如何对付穿过农场的牛的问题。 他现在意识到,友好的品种的标准

比他以前想的稍微微妙一些 -对于品种a,b,如果|a - b|≤K,现在是友好的。 否则是不友好的。给定这条路两边

的田地的顺序,请计算有多少交叉的不良品种对,其中一对品种在前问题被定义。

Input

The first line of input contains N (1≤N≤100,000) and K (0≤K<N). 

The next N lines describe the order, by breed ID, of fields on one side of the road; 

each breed ID is an integer in the range 1…N. The last N lines describe the order, by breed ID, 

of the fields on the other side of the road. Each breed ID appears exactly once in each ordering.

Output

Please output the number of unfriendly crossing pairs of breeds.

Sample Input

4 1
4
3
2
1
1
4
2
3

Sample Output

2
In this example, breeds 1 and 4 are unfriendly and crossing, as are breeds 1 and 3.

题目大意:给定左右两边的号码(号码唯一),左右两边号码相同的连接,如果线条有交叉,且绝对值差值大于k,那么ans++。

题目思路:

将其划分为三维,一维是在左边的位置,二维是在右边的位置,三维是对应的val值,cdq分治即可。

首先对第一维排序 从大到小排序 然后cdq的时候排序第二维从小到大归并 (交叉即为左边大,右边小的边,这样就保证了两维),统计的时候统计前面的只要和我第一维的绝对值差距在k以上的记录答案即可。注意绝对值大于k,所以要加上Query(a[q].val-k-1)和cnt-Query(a[q].val+k)【总数-差值在k以内的】。

AC代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>

using namespace std;

#define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(a,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)

const double EXP = 1e-9;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const double DINF = 0xffffffffffff;
const int mod = 1e9+7;
const int N = 1e5+5;

struct node{
    int x,y;
    int val;
    bool friend operator<(node a,node b){
        return a.x>b.x;
    }
}a[N],tmp[N];

int n,k;
ll ans;


int tree[N]; //tree数组按二进制存,根据n的末尾0的个数存取,树状数组

int lowbit(int x)
{
    return x&(-x);
}

int Query(int x)  //返回1到x的前缀和
{
    if(x<0)
        return 0;
    int res=0;
    while(x)
    {
        res+=tree[x];
        x-=lowbit(x);
    }
    return res;
}

void Add(int x,int v)  //实现a[x]+v;
{
    while(x<=n)        //注意这里是小于等于k,不是n,k是数据范围
    {
        tree[x]+=v;
        x+=lowbit(x);
    }
}

void clearr(int x){
    while(x<=n){
        if(tree[x]==0)
            break;
        tree[x]=0;
        x+=lowbit(x);
    }
}

void cdq(int l,int r){
    if(l>=r) return ;
    int mid = l+r>>1;
    cdq(l,mid);
    cdq(mid+1,r);
    int p=l,q=mid+1,now=l;
    int cnt=0;
    while(p<=mid&&q<=r){
        if(a[p].y<a[q].y){
            Add(a[p].val,1);
            cnt++;
            tmp[now++] = a[p++];
        }
        else{
            int tt=0;
            if(a[q].val+k+1<=n)
                tt=cnt-Query(a[q].val+k);
            ans+=Query(a[q].val-k-1)+tt;
            tmp[now++] = a[q++];
        }
    }
    while(p<=mid){
        Add(a[p].val,1);
        tmp[now++] = a[p++];
    }
    while(q<=r){
        int tt=0;
        if(a[q].val+k+1<=n)
            tt=cnt-Query(a[q].val+k);
        ans+=Query(a[q].val-k-1)+tt;
        tmp[now++] = a[q++];
    }
    for(int i=l;i<=r;i++){
        clearr(a[i].val);
        a[i]=tmp[i];
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    std::ios::sync_with_stdio(false);
    int t;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&t);
        a[t].x = i;
        a[t].val = t;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&t);
        a[t].y = i;
    }
    ans=0;
    sort(a+1,a+1+n);
    cdq(1,n);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/baodream/article/details/82695718