[題解]AT_abc288_d [ABC288D] Range Add Query

WaterSunHB發表於2024-06-23

思路

首先你可以發現,如果一個區間 \([l,r]\) 是一個好的序列,那麼一定 \(i\) 能從 \(l\) 開始 一直到 \(r - k + 1\),將 \(a_{i \sim (i + k - 1)}\) 減掉 \(a_i\)

那麼,當 \(l = 1\) 時,對於每一個 \(i\),我們可以 \(\Theta(n)\) 算出減到 \(a_{i - 1}\) 時,\(a_i\) 的值,記作 \(c_i\)

例如,樣例 1 的 \(c\) 陣列為:

3 -4 2 0 0 0 5

在區間 \([l,r]\) 中,\(a_{(r - k + 2) \sim r}\) 在減掉 \(a_{r - k + 1}\) 之後就不會修改了。那麼這個 \(c\) 陣列的作用就可以體現了,如果 \([l,r]\) 區間是好的序列,當且僅當 \(c_{(r - k + 2) \sim r}\) 全都為 \(0\),因為滿足上述條件意味著無需操作 \(a_{(r - k + 2) \sim r}\) 就可以滿足題意。

考慮動態維護 \(c\) 陣列。顯然的是 \(l = i + 1\)\(c\) 陣列可以由 \(l = i\)\(c\) 陣列轉移。再觀察一下,轉移的時候,是將 \(i \bmod k = t\) 的減去 \(\Delta\)\(i \bmod k = (t + 1) \bmod k\) 的加上 \(\Delta\),其中 \(t = i \bmod k\)

那麼,你用按照下標模 \(k\) 的元素分別用一個樹狀陣列維護其 \(c\) 陣列的值。

Code

#include <bits/stdc++.h>
#define re register
#define int long long

using namespace std;

const int N = 2e5 + 10;
int n,k,q;
int arr[N],c[N];
bool ans[N];

struct Query{
    int r,id;
};
vector<Query> Q[N];

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

struct BIT{
    #define lowbit(x) (x & -x)

    int tr[N];

    inline void modify(int x,int k){
        for (re int i = x;i <= n;i += lowbit(i)) tr[i] += k;
    }

    inline int query(int x){
        int res = 0;
        for (re int i = x;i;i -= lowbit(i)) res += tr[i];
        return res;
    }

    #undef lowbit
}T[11];

signed main(){
    n = read(),k = read();
    for (re int i = 1;i <= n;i++) arr[i] = read();
    for (re int i = 1;i <= n;i++){
        c[i] = arr[i];
        for (re int j = i;j <= i + k - 1;j++) arr[j] -= c[i];
    }
    for (re int ty = 0;ty < k;ty++){
        int be = ty;
        if (!be) be = k;
        for (re int i = be;i <= n;i += k){
            T[ty].modify(i,c[i]); T[ty].modify(i + 1,-c[i]);
        }
    }
    q = read();
    for (re int i = 1;i <= q;i++){
        int l,r;
        l = read(),r = read(); Q[l].push_back({r,i});
    }
    for (re int i = 1;i <= n;i++){
        int be = i % k;
        for (auto p:Q[i]){
            bool falg = true;
            int x = p.r - k + 2;
            for (re int j = x;j <= p.r;j++){
                int val = T[j % k].query(j);
                if (val){
                    falg = false; break;
                }
            }
            ans[p.id] = falg;
        }
        int del = T[be].query(i);
        T[be].modify(1,-del); T[(be + 1) % k].modify(1,del);
    }
    for (re int i = 1;i <= q;i++){
        if (ans[i]) puts("Yes");
        else puts("No");
    }
    return 0;
}

相關文章