AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

洛谷 P3658. [USACO17FEB] Why Did the Cow Cross the Road    原题链接    简单

作者: 作者的头像   Union_Find ,  2025-06-10 18:24:32 · 福建 ,  所有人可见 ,  阅读 3


1


题意

有一个两个长度为 $n$ 的排列,定义种类 $x$ 的线是连接第一个排列和第二排列中值为 $x$ 大的两个位置的线。求无序数对 $(i,j)$ 的个数,要满足 $i$ 的线和 $j$ 的线相交,且 $|i-j| > k$。

$1 \le n \le 10^5,0 \le k < n$。

分析

设 $x_i$ 表示 $i$ 在排列 $a$ 中的位置,$y_i$ 表示 $i$ 在排列 $b$ 中的位置。要让 $i,j$ 的线相交,不妨设 $x_i < x_j$,那么就有 $y_i > y_j$。

现在就是三个限制。

  • $x_i < x_j$。
  • $y_i > y_j$。
  • $|i-j|>k$,即 $i \not \in [j-k,j+k]$。

这三个限制是三位偏序,用 cdq 分治实现即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define il inline
#define N 100005
il int rd(){
    int s = 0, w = 1;
    char ch = getchar();
    for (;ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') w = -1;
    for (;ch >= '0' && ch <= '9'; ch = getchar()) s = ((s << 1) + (s << 3) + ch - '0');
    return s * w;
}
int n, k, a[N], b[N], x[N], y[N], id[N], tr[N], ans;
il bool cmp1(int a, int b){return x[a] < x[b];}
il bool cmp2(int a, int b){return y[a] > y[b];}
il void clr(int x){for (int i = x; i <= n; i += (i & (-i))) tr[i] = 0;}
il void add(int x, int k){for (int i = x; i <= n; i += (i & (-i))) tr[i] += k;}
il int ask(int x){int ans = 0;for (int i = x; i >= 1; i -= (i & (-i))) ans += tr[i];return ans;}
void cdq(int l, int r){
    if (l == r) return ;
    int mid = (l + r) >> 1;
    sort (id + l, id + r + 1, cmp1);
    cdq(l, mid), cdq(mid + 1, r);
    sort (id + l, id + mid + 1, cmp2), sort (id + mid + 1, id + r + 1, cmp2);
    for (int i = l, j = mid + 1; j <= r; j++){
        for (; i <= mid && y[id[i]] > y[id[j]]; i++) add(id[i], 1);
        if (id[j] - k > 1) ans += ask(id[j] - k - 1);
        if (id[j] + k < n) ans += ask(n) - ask(id[j] + k);
    }
    for (int i = l; i <= mid; i++) clr(id[i]);
}
signed main(){
    n = rd(), k = rd();
    for (int i = 1; i <= n; i++) id[i] = i;
    for (int i = 1; i <= n; i++) x[a[i] = rd()] = i;
    for (int i = 1; i <= n; i++) y[b[i] = rd()] = i;
    cdq(1, n);
    printf ("%lld\n", ans);
    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息