詳細なブロック

hzwer的9题
https://loj.ac/problem/6277
https://loj.ac/problem/6278
https://loj.ac/problem/6279
https://loj.ac/problem/6280
https://loj.ac/problem/6281
https://loj.ac/problem/6282
https://loj.ac/problem/6283
https://loj.ac/problem/6284
https://loj.ac/problem/6285

(\ \テキスト{ブロックであるエレガント暴力} \)

\(\ {テキスト、おそらくこのような何かを考えて:小さな列挙定数のブロックとの不満の一部ならばブロッククエリ内のメンテナンスのsqrt(n)の時間ブロックは、クエリ間隔である} \)

\(\ {テキスト個人的な木のラインよりも感じますが、コードは、そっとツリーラインよりも(シンプルかつ長い思考は簡単です} \)

(\ \テキスト\){次に、ブロックとは、セグメントツリー一般O2(大きいため、セグメントツリーの定数を送信しました}

(\ \テキスト{デジタル複雑にブロックが各ブロックされている前処理O(N)} \)

(\ \テキスト{部と、クエリを変更するには、以下であるもの} \) \(2 \ \ SQRT(N)\)

(\ \テキスト{証明:つのブロックのサイズことを} \)\(\ SQRT(N)\) {あまり左部と右部のうち\(\テキストは、最悪の場合($ \ SQRT(n)は$)証明するのは簡単です} \)

(\ \テキスト{ブロックの時間的複雑さは、おそらくある} \) \(\シータ(N + Q *の\のSQRT(N))\)
配列の長さqにN-意味操作の数のクエリ修飾を指す)
\(\テキスト\ {上記容易セグメントツリーより実現し、単に考え基本ブロックのブロックです})

(\ \テキスト{} 1 \ブロック)
ブロック修飾部1は、クエリの一点です

私たちは、ブロックを維持するために、配列を使用
ブロックは、それが変更され、直接暴力のうち、よりである場合は、修正するために、このブロックを追加することができます値が含まれている場合、間隔を変更した場合

そして、変更された値と値自体クエリ出力ブロック

// Isaunoya
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std ;
const int N = 50000 + 5 ;
const int Bl = 300 + 5 ;
struct node {
    int l , r ;
    int add ;
} ;
int n ;
int a[N] ;
node atag[Bl] ;
int bl[N] ; int unt ;
inline void change(int l , int r , int c) {
    for(register int i = l ; i <= min(bl[l] * unt , r) ; i ++)
        a[i] += c ;
    if(bl[l] != bl[r])
        for(register int i = (bl[r] - 1) * unt + 1 ; i <= r ; i ++)
            a[i] += c ;
    for(register int i = bl[l] + 1 ; i <= bl[r] - 1 ; i ++)
        atag[i].add += c ;
}
signed main() {
    ios::sync_with_stdio(false) ;
    cin >> n ;
    for(register int i = 1 ; i <= n ; i ++) cin >> a[i] ;
    unt = sqrt(n) ;
    for(register int i = 1 ; i <= n ; i ++) {
        bl[i] = (i - 1) / unt + 1 ;
    }
    for(register int i = 1 ; i <= n ; i ++) {
        int opt ;
        cin >> opt ;
        if(opt == 0) {
            int l , r , c ;
            cin >> l >> r >> c ;
            change(l , r , c) ;
        }
        else {
            int l , r , c ;
            cin >> l >> r >> c ;
            cout << a[r] + atag[bl[r]].add << endl ;
        }
    }
    return 0 ;
}

(\ \テキスト{} 2 \ブロック)

二つのブロック部がよりクエリー間隔以下変更しようとしている\(C ^ 2 \)の数
維持ビットセット(セット自動選別これらの問題を

#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline int read() {
    register int x = 0;
    register int f = 1;
    register char c;
#define gc c = getchar()
    while (isspace(gc))
        ;
    c == '-' ? gc, f = -1 : 0;
    while (x = (x << 3) + (x << 1) + (c & 15), isdigit(gc))
        ;
    return x * f;
}
const int N = 100000 + 5;
const int Bl = 400 + 5;
int n;
int a[N];
struct node {
    int add;
};
node atag[Bl];
int unt;
int bl[N];
set<int> st[Bl];
inline void change(int l, int r, int c) {
    for (register int i = l ; i <= min(bl[l] * unt, r); i++) {
        st[bl[i]].erase(a[i]);
        a[i] += c;
        st[bl[i]].insert(a[i]);
    }
    if (bl[l] != bl[r]) {
        for (register int i = (bl[r] - 1) * unt + 1; i <= r; i++) {
            st[bl[i]].erase(a[i]);
            a[i] += c;
            st[bl[i]].insert(a[i]);
        }
    }
    for (register int i = bl[l] + 1; i <= bl[r] - 1; i++) atag[i].add += c;
}
inline int query(int l, int r, int c) {
    int ans = INT_MIN ;
    for (register int i = l; i <= min(bl[l] * unt, r); i++)
        if (a[i] + atag[bl[l]].add < c)
            ans = max(a[i] + atag[bl[l]].add, ans);
    if (bl[l] != bl[r]) {
        for (register int i = (bl[r] - 1) * unt + 1; i <= r; i++)
            if (a[i] + atag[bl[r]].add < c)
                ans = max(a[i] + atag[bl[r]].add, ans);
    }
    for (register int i = bl[l] + 1; i <= bl[r] - 1; i++) {
        int s = c - atag[i].add;
        auto find = st[i].lower_bound(s);
        if (find == st[i].begin()) continue ;
        find--;
        ans = max(ans, *find + atag[i].add);
    }
    return ans == INT_MIN ? -1 : ans ;
}
signed main() {
    n = read();
    unt = 500 + 5 ; 
    for (register int i = 1; i <= n; i++) a[i] = read();
    for (register int i = 1; i <= n; i++) bl[i] = (i - 1) / unt + 1;
    for (register int i = 1; i <= n; i++) {
        st[bl[i]].insert(a[i]);
    }
    for (register int i = 1; i <= n; i++) {
        int opt = read(), L = read(), R = read(), c = read();
        if (opt)
            printf("%d\n", query(L, R, c));
        else
            change(L, R, c);
    }
    return 0;
}

(\ \テキスト{} 3 \ブロック)

のX X前駆体、すなわち最大数よりも小さい値未満の尋問区域修正区間内のブロック3

また、セット維持するために用い
、続いて\(下_ \結合\)の半分
(パートC ++コンテンツ11を

// Isaunoya
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline int read() {
    register int x = 0;
    register int f = 1;
    register char c;
#define gc c = getchar()
    while (isspace(gc))
        ;
    c == '-' ? gc, f = -1 : 0;
    while (x = (x << 3) + (x << 1) + (c & 15), isdigit(gc))
        ;
    return x * f;
}
const int N = 100000 + 5;
const int Bl = 400 + 5;
int n;
int a[N];
struct node {
    int add;
};
node atag[Bl];
int unt;
int bl[N];
set<int> st[Bl];
inline void change(int l, int r, int c) {
    for (register int i = l; i <= min(bl[l] * unt, r); i++) {
        st[bl[i]].erase(a[i]);
        a[i] += c;
        st[bl[i]].insert(a[i]);
    }
    if (bl[l] != bl[r]) {
        for (register int i = (bl[r] - 1) * unt + 1; i <= r; i++) {
            st[bl[i]].erase(a[i]);
            a[i] += c;
            st[bl[i]].insert(a[i]);
        }
    }
    for (register int i = bl[l] + 1; i <= bl[r] - 1; i++) atag[i].add += c;
}
inline int query(int l, int r, int c) {
    int ans = -1;
    for (register int i = l; i <= min(bl[l] * unt, r); i++)
        if (a[i] + atag[bl[l]].add < c)
            ans = max(a[i] + atag[bl[l]].add, ans);
    if (bl[l] != bl[r]) {
        for (register int i = (bl[r] - 1) * unt + 1; i <= r; i++)
            if (a[i] + atag[bl[r]].add < c)
                ans = max(a[i] + atag[bl[l]].add, ans);
    }
    for (register int i = bl[l] + 1; i <= bl[r] - 1; i++) {
        int s = c - atag[i].add;
        auto find = st[i].lower_bound(s);
        if (find == st[i].begin()) continue ;
        find--;
        ans = max(ans, *find + atag[i].add);
    }
    return ans;
}
signed main() {
    n = read();
    unt = sqrt(n);
    for (register int i = 1; i <= n; i++) a[i] = read();
    for (register int i = 1; i <= n; i++) bl[i] = (i - 1) / unt + 1;
    for (register int i = 1; i <= n; i++) {
        st[bl[i]].insert(a[i]);
    }
    for (register int i = 1; i <= n; i++) {
        int opt = read(), L = read(), R = read(), c = read();
        if (opt)
            printf("%d\n", query(L, R, c));
        else
            change(L, R, c);
    }
    return 0;
}

\({\テキスト{4}}ブロック\)

図4は、ブロック加算間隔修正間隔である
インターバルと%\(1 + C \)

私たちは、メンテナンス間隔のアレイの使用を考慮して、配列を使用してブロック全体のメンテナンスを変更します

メンテナンス間隔とは、暴力的な修飾部分を指し

// Isaunoya
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>

using namespace std ;
#define int long long
inline int read() { register int x = 0 ; register int f = 1 ; register char c ;
#define gc c = getchar()
    while(isspace(gc)) ;
    c == '-' ? gc , f = -1 : 0 ;
    while(x = (x << 1) + (x << 3) + (c ^ 48) , isdigit(gc)) ;
    return x * f ;
}

int n ;
const int N = 50000 + 5 ;
int a[N] ;
int bl[N] ;
int sum[N] ;
int atag[N] ;
int unt ;
inline void change(int l , int r , int c) {
    for(register int i = l ; i <= min(r , bl[l] * unt) ; i ++) {
        a[i] += c ;
        sum[bl[l]] += c ;
    }
    if(bl[l] != bl[r])
        for(register int i = (bl[r] - 1) * unt + 1 ; i <= r ; i ++) {
            a[i] += c ;
            sum[bl[r]] += c ;
        }
    for(register int i = bl[l] + 1 ; i <= bl[r] - 1 ; i ++) atag[i] += c ;
    return ;
}
inline int query(int l , int r , int c) { int ans = 0 ;
    for(register int i = l ; i <= min(r , bl[l] * unt) ; i ++) {
        ans += a[i] + atag[bl[l]] ;
        ans %= c ;
    }
    if(bl[l] != bl[r])
        for(register int i = (bl[r] - 1) * unt + 1 ; i <= r ; i ++) {
            ans += a[i] + atag[bl[r]] ;
            ans %= c ;
        }
    for(register int i = bl[l] + 1 ; i <= bl[r] - 1 ; i ++)
        ans = (ans + sum[i] + atag[i] * unt) % c ;
    return ans ;
}
signed main() {
    n = read() ; unt = sqrt(n) ;
    for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
    for(register int i = 1 ; i <= n ; i ++) bl[i] = (i - 1) / unt + 1 ;
    for(register int i = 1 ; i <= n ; i ++) {
        sum[bl[i]] += a[i] ;
    }
    for(register int i = 1 ;i <= n ; i ++) {
        int opt = read() ;
        if(opt == 0) {
            int l = read() , r = read() , c = read() ;
            change(l , r , c) ;
        }
        if(opt == 1) {
            int l = read() , r = read() , c = read() ;
            printf("%lld\n" , query(l , r , c + 1)) ;
        }
    }
    return 0 ;
}

おすすめ

転載: www.cnblogs.com/qf-breeze/p/11361618.html