bzoj 4991 [Usaco2017 Feb]Why Did the Cow Cross the Road III

http://www.elijahqi.win/archives/3206
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

#include<cstdio>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++; 
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int N=100100;
struct node{
    int a,b,tim;
}qr[N],tmp[N];
int s[N],n,k;ll ans;
inline void add(int x,int v){while(x<=n) s[x]+=v,x+=x&-x; }
inline int query(int x){static int tmp;
    if (x<0) return 0;
    for (tmp=0;x;x-=x&-x) tmp+=s[x];return tmp;
}
inline void clear(int x){
    while(x<=n) if (!s[x]) return;else s[x]=0,x+=x&-x;
}
inline bool cmp(const node &a,const node &b){return a.a>b.a;}
inline void cdq(int l,int r){
    if (l==r) return;int mid=l+r>>1;
    cdq(l,mid);cdq(mid+1,r);int l1=l,l2=mid+1,now=l,cnt=0;
    while(l1<=mid&&l2<=r){
        if (qr[l1].b<qr[l2].b) ++cnt,tmp[now]=qr[l1],add(qr[l1].tim,1),++now,++l1;else tmp[now]=qr[l2],
        ans+=query(qr[l2].tim-k-1),ans+=qr[l2].tim+k+1>n?0:(cnt-query(qr[l2].tim+k)),++now,++l2;
    }while(l1<=mid) tmp[now]=qr[l1],++now,++l1;
    while(l2<=r) tmp[now]=qr[l2],ans+=query(qr[l2].tim-k-1),
    ans+=qr[l2].tim+k>n?0:(cnt-query(qr[l2].tim+k)),++now,++l2;
    for (int i=l;i<=r;++i) qr[i]=tmp[i],clear(qr[i].tim);
}
int main(){
    freopen("bzoj4991.in","r",stdin);
    n=read();k=read();
    for (int i=1;i<=n;++i) qr[read()].a=i,qr[i].tim=i;
    for (int i=1;i<=n;++i) qr[read()].b=i;sort(qr+1,qr+n+1,cmp);
    cdq(1,n);printf("%lld\n",ans); 
//  for (int i=1;i<=cnt;++i) printf("%d %d %d %d\n",qr[i].tim,qr[i].a,qr[i].b,qr[i].op);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值