ZOJ 4003 Distance双指针维护区间

博客介绍了如何利用双指针技巧解决一道关于区间和的竞赛题目。题目要求判断两个长度相同的数列区间是否满足特定条件,即区间元素之差的绝对值的p次幂之和不超过给定阈值V。通过枚举区间起点并动态计算区间和,可以有效地找出所有满足条件的区间组合,从而求得答案。
摘要由CSDN通过智能技术生成

ZOJ 4003 Distance双指针维护区间


传送门: https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370154

题意

对 于 两 个 长 度 相 同 的 区 间 a 和 b , 如 果 ∑ ∣ a i − b i ∣ p ≤ V , 则 成 这 两 个 区 间 为 g o o d 区 间 . 对于两个长度相同的区间a和b,如果\sum|a_i-b_i|^p\leq V,则成这两个区间为good 区间. abaibipVgood.
给 出 两 个 长 度 相 同 的 数 列 , 在 这 两 个 数 列 中 分 别 选 择 两 个 区 间 , 存 在 多 少 个 g o o d 区 间 。 给出两个长度相同的数列,在这两个数列中分别选择两个区间,存在多少个good区间。 good

思路

因 为 ∑ ∣ a i − b i ∣ p 有 绝 对 值 , 所 以 每 增 加 一 个 值 , 都 会 增 加 。 因为\sum|a_i-b_i|^p有绝对值,所以每增加一个值,都会增加。 aibip
假 设 我 们 找 到 一 个 区 间 [ l 1 , r 1 ] 、 [ l 2 , r 2 ] , 则 l ∈ [ l 1 , r 1 ] , l ′ ∈ [ l 2 , r 2 ] 都 是 可 以 的 。 假设我们找到一个区间[l1,r1]、[l2,r2],则l\in [l1,r1],l'\in [l2,r2]都是可以的。 [l1,r1][l2,r2]l[l1,r1]l[l2,r2]

所 以 我 们 可 以 枚 举 区 间 起 点 , 然 后 计 算 终 点 , 最 后 维 护 区 间 , 更 新 和 统 计 答 案 即 可 。 所以我们可以枚举区间起点,然后计算终点,最后维护区间,更新和统计答案即可。

Code

#include "bits/stdc++.h"

using namespace std;

typedef long long ll;

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a;
        a = a * a;
        b >>= 1;
    }
    return ans;
}

void solve() {
    int _; cin >> _;
    while(_--) {
        int n; ll V, p;
        cin >> n >> V >> p;
        vector<ll> x(n + 10);
        vector<ll> y(n + 10);
        for(int i = 1;i <= n; i++) cin >> x[i];
        for(int i = 1;i <= n; i++) cin >> y[i];
        ll ans = 0;
        for(int len = 0;len <= n - 1; len++) { // 枚举指针距离
            int l1 = 1, r1 = 1; // a
            int l2 = 1 + len, r2 = 1 + len; // b
            ll cnt = quick_pow(abs(x[l1] - y[l2]), p);
            while(r2 <= n) { // 先让b动区间
                if(cnt <= V) {
                    ans += r1 - l1 + 1;
                    r1++;
                    r2++;
                    cnt += quick_pow(abs(x[r1] - y[r2]), p);
                }
                else {
                    cnt -= quick_pow(abs(x[l1] - y[l2]), p);
                    l1++;
                    l2++;
                    if(l1 > r1) {
                        r1++;
                        r2++;
                        cnt += quick_pow(abs(x[r1] - y[r2]), p);
                    }
                }
            }
            if(len == 0) continue;
            l1 = 1 + len; r1 = 1 + len;
            l2 = 1; r2 = 1;
            cnt = quick_pow(abs(x[l1] - y[l2]), p);
            while(r1 <= n) {
                if(cnt <= V) {
                    ans += r2 - l2 + 1;
                    r1++;
                    r2++;
                    cnt += quick_pow(abs(x[r1] - y[r2]), p);
                }
                else {
                    cnt -= quick_pow(abs(x[l1] - y[l2]), p);
                    l1++;
                    l2++;
                    if(l2 > r2) {
                        r1++;
                        r2++;
                        cnt += quick_pow(abs(x[r1] - y[r2]), p);
                    }
                }
            }
        }
        cout << ans << endl;
    }
}

signed main() {
    solve();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值