1. 程式人生 > 實用技巧 >LibreOJ 6277 數列分塊入門 1(分塊區修,單點查詢)

LibreOJ 6277 數列分塊入門 1(分塊區修,單點查詢)

題目連結

解題思路

  分塊模版|

程式碼

const int maxn = 5e4+10;
int n,sz,num,a[maxn],ls[maxn],rs[maxn],belong[maxn],lazy[maxn];
void build() {
    num = (n+sz-1)/sz; //分塊大小
    for (int i = 1; i<=num; ++i) {
        ls[i] = (i-1)*sz+1, rs[i] = i*sz; //每個塊左右邊界
    }
    rs[num] = n;
    for (int i = 1; i<=n; ++i) belong[i] = (i-1)/sz+1; //每個元素所屬塊
}
void update(int l, int r, int c) {
    if (belong[l]==belong[r]) { //同一個塊直接暴力
        for (int i = l; i<=r; ++i) a[i] += c;
        return;
    }
    //不同塊左右暴力,中間塊打標記
    for (int i = belong[l]+1; i<belong[r]; ++i) lazy[i] += c;
    for (int i = l; i<=rs[belong[l]]; ++i) a[i] += c;
    for (int i = ls[belong[r]]; i<=r; ++i) a[i] += c;
}
int find(int p) {
    if (lazy[belong[p]]) { //塊內標記下傳
        for (int i = ls[belong[p]]; i<=rs[belong[p]]; ++i) a[i] += lazy[belong[p]];
        lazy[belong[p]] = 0;
    }
    return a[p];
}
int main() {
    scanf("%d",&n); 
    for (int i = 1; i<=n; ++i) scanf("%d",&a[i]);
    sz = sqrt(n); build();
    for (int i = 1,op,l,r,c; i<=n; ++i) {
        scanf("%d%d%d%d",&op,&l,&r,&c);
        if (!op) update(l,r,c);
        else printf("%d\n",find(r));
    }
    return 0;                                                                 
}