P3658 [USACO17FEB]Why Did the Cow Cross the Road III P
主要思路
cdq 分治。
思路
我们可以从某些不知名渠道中得知这道题是 cdq 分治,那么我们就可以来想一下三个条件了。
- 因为那两条线一定要相交,所以我们就要让 \(p1_x<p2_x\) 并且 \(p1_y>p2_y\) 而 \(p1_i\) 和 \(p2_i\) 数组表示 \(i\) 在第一个数组和第二个数组中的位置。
- \(|x-y|>k\) 这个其实就那树状数组枚举就好了。
所以这道题我们就可以化简成一个三维偏序那道题了,我们只需要现将 \(p1\) 和 \(p2\) 从排序来处理然后再用一个树状数组来处理后面那个了,我们可以发现对于答案要分两种情况讨论因为可以 \(x\) 大或者 \(y\) 大。
代码
#include <bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;--i)
#define int long long
#define gh int
#define ru(x) cin>>x
using namespace std ;
const int N=2e6+10;
int tr[N],n,k,res;
struct node {
int x,y;
int val;
} s[N];
int lowbit(int x) {
return x&-x;
}
int Ans(int x) {
x=max(x,0ll);
x=min(x,n);
int res=0;
while(x) {
res+=tr[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int k) {
while(x<=n) {
tr[x]+=k;
x+=lowbit(x);
}
}
bool cmp(node a,node b) {
return a.x<b.x;
}
bool cmp1(node a,node b) {
return a.y>b.y;
}
void cdq(int l,int r) {//模板
if(l==r) return ;
int mid=l+r>>1;
cdq(l,mid);
cdq(mid+1,r);
sort(s+l,s+1+mid,cmp1);
sort(s+1+mid,s+1+r,cmp1);
int j=l;
rep(i,mid+1,r) {
while(j<=mid&&s[j].y>s[i].y) {
add(s[j].val,1);
j++;
}
res+=Ans(s[i].val-k-1)+Ans(n)-Ans(s[i].val+k); //分两种情况讨论
}
rep(i,l,j-1) add(s[i].val,-1); //为了不改变清零
}
signed main() {
ru(n),ru(k);
rep(i,1,n) {
gh x;
ru(x);
s[x].val=x;
s[x].x=i;
}
rep(i,1,n) {
gh x;
ru(x);
s[x].y=i;
}
sort(s+1,s+1+n,cmp); //先按第一维排序
cdq(1,n);
cout<<res<<endl;
return false;
}

浙公网安备 33010602011771号