数列分块入门1

Image

第一题是y总的板子,但是y总的分块就讲了这个基础题目,我觉得还是太浅了,后来讲的就是链表分块,但是后来我去洛谷交了一个数据大一点点的题目,发现会卡常,还算不建议用y总的板子了

代码:

#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 350, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
template <typename T>
struct BIT1
{
    int n;
    vector<T> tr;
    BIT1(int n) : n(n), tr(n + 1) {}
    void add(int x, T v)
    {
        for (; x <= n; x += x & -x)
            tr[x] += v;
    }
    T sum(int x)
    {
        T r = 0;
        for (; x; x -= x & -x)
            r += tr[x];
        return r;
    }
    T range(int l, int r) { return sum(r) - sum(l - 1); }
};
template <typename T>
struct BIT2
{
    int n, m;
    vector<vector<T>> t1, t2, t3, t4;
    BIT2(int n_ = 0, int m_ = 0) { init(n_, m_); }
    void init(int n_, int m_)
    {
        n = n_;
        m = m_;
        t1.assign(n + 1, vector<T>(m + 1, T{}));
        t2.assign(n + 1, vector<T>(m + 1, T{}));
        t3.assign(n + 1, vector<T>(m + 1, T{}));
        t4.assign(n + 1, vector<T>(m + 1, T{}));
    }
    void _add(int x, int y, const T &v)
    {
        for (int i = x; i <= n; i += i & -i)
            for (int j = y; j <= m; j += j & -j)
            {
                t1[i][j] += v;
                t2[i][j] += v * x;
                t3[i][j] += v * y;
                t4[i][j] += v * x * y;
            }
    }
    void rangeAdd(int x1, int y1, int x2, int y2, const T &v)
    {
        _add(x1, y1, v);
        _add(x1, y2 + 1, -v);
        _add(x2 + 1, y1, -v);
        _add(x2 + 1, y2 + 1, v);
    }
    T prefixSum(int x, int y)
    {
        T r{};
        for (int i = x; i > 0; i -= i & -i)
            for (int j = y; j > 0; j -= j & -j)
                r += t1[i][j] * (x + 1) * (y + 1) - t2[i][j] * (y + 1) - t3[i][j] * (x + 1) + t4[i][j];
        return r;
    }
    T rangeSum(int x1, int y1, int x2, int y2)
    {
        if (x1 > x2 || y1 > y2)
            return T{};
        return prefixSum(x2, y2) - prefixSum(x1 - 1, y2) - prefixSum(x2, y1 - 1) + prefixSum(x1 - 1, y1 - 1);
    }
};
struct Random
{
    mt19937_64 rng;
    Random() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}
    ull rand_ull(ull max_val = -1) { return rng() % (max_val + 1); }
    ll rand_ll(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
    int rand_int(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); }
    double rand_db(double l, double r) { return uniform_real_distribution<double>(l, r)(rng); }
    bool rand_bool(double p = 0.5) { return bernoulli_distribution(p)(rng); }
    template <typename T>
    void shuffle(vector<T> &v) { std::shuffle(v.begin(), v.end(), rng); }
};
ll qmi(ll a, ll b, ll p)
{
    ll res = 1 % p;
    a %= p;
    while (b)
    {
        if (b & 1)
            res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
/*

*/
ll n, m, len;
ll a[N], add[M], sum[M];
ll get(ll i)
{
    return i / len;
}

void change(ll l, ll r, ll d)
{
    if (get(l) == get(r))
    {
        rep(i, l, r) a[i] += d, sum[get(i)] += d;
    }
    else
    {
        ll i = l, j = r;
        while (get(i) == get(l))
            a[i] += d, sum[get(i)] += d, i++;
        while (get(j) == get(r))
            a[j] += d, sum[get(j)] += d, j--;
        rep(k, get(i), get(j))
        {
            sum[k] += len * d;
            add[k] += d;
        }
    }
}

ll query(ll l, ll r)
{
    ll ret = 0;
    if (get(l) == get(r))
    {
        rep(i, l, r) ret += a[i] + add[get(i)];
    }
    else
    {
        ll i = l, j = r;
        while (get(i) == get(l))
            ret += a[i] + add[get(i)], i++;
        while (get(j) == get(r))
            ret += a[j] + add[get(j)], j--;
        rep(k, get(i), get(j))
        {
            ret += sum[k];
        }
    }
    return ret;
}

void solve()
{
    cin >> n ;
    m=n;
    rep(i, 1, n) cin >> a[i];
    len = sqrt(n);
    rep(i, 1, n)
    {
        sum[get(i)] += a[i];
    }
    while (m--)
    {
        string op;
        cin >> op;
        if (op == "0")
        {
            ll l, r, d;
            cin >> l >> r >> d;
            change(l, r, d);
        }
        else
        {
            ll l, r,d;
            cin >> l >> r>>d;
            ll ans = query(r, r);
            cout << ans << endl;
        }
    }
}

int main()
{
    IOS;

    int _ = 1;
    // cin>>_;//如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

下面的是暂时不卡常的代码:

#include <bits/stdc++.h>
using namespace std;
//CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p<<1
#define rc p<<1|1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x)&(-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps=1e-5;
const int N = 3e5 + 10,M=550,K=26;
const ll MOD = 1e9 + 7,Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template<typename T> bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template<typename T> bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template<typename T> void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
template<typename T> struct BIT1 { int n; vector<T> tr; BIT1(int n) : n(n), tr(n+1) {} void add(int x, T v) { for(;x<=n;x+=x&-x) tr[x]+=v; } T sum(int x) { T r=0; for(;x;x-=x&-x) r+=tr[x]; return r; } T range(int l, int r) { return sum(r)-sum(l-1); } };
template<typename T> struct BIT2 { int n,m; vector<vector<T>> t1,t2,t3,t4; BIT2(int n_=0,int m_=0) { init(n_,m_); } void init(int n_,int m_) { n=n_; m=m_; t1.assign(n+1,vector<T>(m+1,T{})); t2.assign(n+1,vector<T>(m+1,T{})); t3.assign(n+1,vector<T>(m+1,T{})); t4.assign(n+1,vector<T>(m+1,T{})); } void _add(int x,int y,const T& v) { for(int i=x;i<=n;i+=i&-i) for(int j=y;j<=m;j+=j&-j) { t1[i][j]+=v; t2[i][j]+=v*x; t3[i][j]+=v*y; t4[i][j]+=v*x*y; } } void rangeAdd(int x1,int y1,int x2,int y2,const T& v) { _add(x1,y1,v); _add(x1,y2+1,-v); _add(x2+1,y1,-v); _add(x2+1,y2+1,v); } T prefixSum(int x,int y) { T r{}; for(int i=x;i>0;i-=i&-i) for(int j=y;j>0;j-=j&-j) r+=t1[i][j]*(x+1)*(y+1)-t2[i][j]*(y+1)-t3[i][j]*(x+1)+t4[i][j]; return r; } T rangeSum(int x1,int y1,int x2,int y2) { if(x1>x2||y1>y2) return T{}; return prefixSum(x2,y2)-prefixSum(x1-1,y2)-prefixSum(x2,y1-1)+prefixSum(x1-1,y1-1); } };
struct Random { mt19937_64 rng; Random() : rng(chrono::steady_clock::now().time_since_epoch().count()) {} ull rand_ull(ull max_val = -1) { return rng() % (max_val + 1); } ll rand_ll(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); } int rand_int(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); } double rand_db(double l, double r) { return uniform_real_distribution<double>(l, r)(rng); } bool rand_bool(double p = 0.5) { return bernoulli_distribution(p)(rng); } template<typename T> void shuffle(vector<T> &v) { std::shuffle(v.begin(), v.end(), rng); } };
ll qmi(ll a, ll b, ll p) { ll res = 1 % p; a %= p; while (b) { if (b & 1) res = res * a % p; a = a * a % p; b >>= 1; } return res; }
/*
  
*/
ll n, len;
ll a[N], add[M]; // 移除了不必要的sum数组

ll get(ll i) {
    return (i - 1) / len; // 通常块编号从0开始,或者用(i-1)/len +1从1开始,这里根据你的习惯调整。注意与后续操作匹配。
}

void change(ll l, ll r, ll d) {
    int bl = get(l), br = get(r);
    if (bl == br) {
        // 情况1:l和r在同一个块内,暴力修改
        for (ll i = l; i <= r; i++) {
            a[i] += d;
        }
    } else {
        // 情况2:跨块
        // 处理左侧不完整块
        for (ll i = l; i <= (bl + 1) * len; i++) { // 假设块编号从0开始,bl是l所在的块
            a[i] += d;
        }
        // 处理右侧不完整块
        for (ll i = br * len + 1; i <= r; i++) { // br是r所在的块
            a[i] += d;
        }
        // 处理中间的完整块
        for (int k = bl + 1; k < br; k++) {
            add[k] += d;
        }
    }
}

void solve() {
    cin >> n;
    len = sqrt(n); // 块的大小
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }

    int m = n;
    while (m--) {
        int opt;
        ll l, r, c;
        cin >> opt >> l >> r >> c;
        if (opt == 0) {
            change(l, r, c);
        } else {
            // 单点查询:直接输出 a[r] + 其所在块的add标记
            cout << a[r] + add[get(r)] << endl;
        }
    }
}

int main() {
    IOS;
    int _ = 1;
    while (_--) {
        solve();
    }
    return 0;
}

数列分块入门2

Image

代码:

#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 350, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
template <typename T>
struct BIT1
{
    int n;
    vector<T> tr;
    BIT1(int n) : n(n), tr(n + 1) {}
    void add(int x, T v)
    {
        for (; x <= n; x += x & -x)
            tr[x] += v;
    }
    T sum(int x)
    {
        T r = 0;
        for (; x; x -= x & -x)
            r += tr[x];
        return r;
    }
    T range(int l, int r) { return sum(r) - sum(l - 1); }
};
template <typename T>
struct BIT2
{
    int n, m;
    vector<vector<T>> t1, t2, t3, t4;
    BIT2(int n_ = 0, int m_ = 0) { init(n_, m_); }
    void init(int n_, int m_)
    {
        n = n_;
        m = m_;
        t1.assign(n + 1, vector<T>(m + 1, T{}));
        t2.assign(n + 1, vector<T>(m + 1, T{}));
        t3.assign(n + 1, vector<T>(m + 1, T{}));
        t4.assign(n + 1, vector<T>(m + 1, T{}));
    }
    void _add(int x, int y, const T &v)
    {
        for (int i = x; i <= n; i += i & -i)
            for (int j = y; j <= m; j += j & -j)
            {
                t1[i][j] += v;
                t2[i][j] += v * x;
                t3[i][j] += v * y;
                t4[i][j] += v * x * y;
            }
    }
    void rangeAdd(int x1, int y1, int x2, int y2, const T &v)
    {
        _add(x1, y1, v);
        _add(x1, y2 + 1, -v);
        _add(x2 + 1, y1, -v);
        _add(x2 + 1, y2 + 1, v);
    }
    T prefixSum(int x, int y)
    {
        T r{};
        for (int i = x; i > 0; i -= i & -i)
            for (int j = y; j > 0; j -= j & -j)
                r += t1[i][j] * (x + 1) * (y + 1) - t2[i][j] * (y + 1) - t3[i][j] * (x + 1) + t4[i][j];
        return r;
    }
    T rangeSum(int x1, int y1, int x2, int y2)
    {
        if (x1 > x2 || y1 > y2)
            return T{};
        return prefixSum(x2, y2) - prefixSum(x1 - 1, y2) - prefixSum(x2, y1 - 1) + prefixSum(x1 - 1, y1 - 1);
    }
};
struct Random
{
    mt19937_64 rng;
    Random() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}
    ull rand_ull(ull max_val = -1) { return rng() % (max_val + 1); }
    ll rand_ll(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
    int rand_int(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); }
    double rand_db(double l, double r) { return uniform_real_distribution<double>(l, r)(rng); }
    bool rand_bool(double p = 0.5) { return bernoulli_distribution(p)(rng); }
    template <typename T>
    void shuffle(vector<T> &v) { std::shuffle(v.begin(), v.end(), rng); }
};
ll qmi(ll a, ll b, ll p)
{
    ll res = 1 % p;
    a %= p;
    while (b)
    {
        if (b & 1)
            res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
/*

*/

ll n, len;
ll a[N], add[M];
vll sorted[M];

ll get(ll i)
{
    return (i - 1) / len + 1;
}

void build(ll block)
{
    ll st = (block - 1) * len + 1;
    ll ed = min((block)*len, n);
    sorted[block].clear();
    rep(i, st, ed)
    {
        sorted[block].push_back(a[i]);
    }
    sort(all(sorted[block]));
}

void change(ll l, ll r, ll d)
{
    ll bl = get(l), br = get(r);
    if (bl == br)
    {
        rep(i, l, r) a[i] += d;
        build(bl);
    }
    else
    {
        rep(i, l, (bl)*len) a[i] += d;
        build(bl);
        rep(i, (br - 1) * len + 1, r) a[i] += d;
        build(br);
        rep(i, bl + 1, br - 1) add[i] += d;
    }
}

ll query_less(ll l, ll r, ll c)
{
    ll x = c * c;
    ll bl = get(l), br = get(r);
    ll ans = 0;
    if (bl == br)
    {
        rep(i, l, r)
        {
            if (a[i] + add[bl] < x)
                ans++;
        }
    }
    else
    {
        rep(i, l, bl * len)
        {
            if (a[i] + add[bl] < x)
                ans++;
        }
        rep(i, (br - 1) * len + 1, r)
        {
            if (a[i] + add[br] < x)
                ans++;
        }
        rep(i, bl + 1, br - 1)
        {
            ll d = x - add[i];
            ll pos = lower_bound(all(sorted[i]), d) - sorted[i].begin();
            ans += pos;
        }
    }
    return ans;
}

void solve()
{
   
    cin >> n;
    len = sqrt(n);
    ll t = get(n);
    rep(i, 1, n) cin >> a[i];
     rep(i, 1, t)
    {
        add[i] = 0;
        build(i);
    }
    rep(i, 1, n)
    {
        ll op, l, r, d;
        cin >> op >> l >> r >> d;
        if (op == 0)
        {
            change(l, r, d);
        }
        else
        {
            ll ans = query_less(l, r, d);
            cout << ans << endl;
        }
    }
}

int main()
{
    IOS;

    int _ = 1;
    // cin>>_;//如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

数列分块入门3

Image

#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 2e5 + 10, M = 550, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
template <typename T>
struct BIT1
{
    int n;
    vector<T> tr;
    BIT1(int n) : n(n), tr(n + 1) {}
    void add(int x, T v)
    {
        for (; x <= n; x += x & -x)
            tr[x] += v;
    }
    T sum(int x)
    {
        T r = 0;
        for (; x; x -= x & -x)
            r += tr[x];
        return r;
    }
    T range(int l, int r) { return sum(r) - sum(l - 1); }
};
template <typename T>
struct BIT2
{
    int n, m;
    vector<vector<T>> t1, t2, t3, t4;
    BIT2(int n_ = 0, int m_ = 0) { init(n_, m_); }
    void init(int n_, int m_)
    {
        n = n_;
        m = m_;
        t1.assign(n + 1, vector<T>(m + 1, T{}));
        t2.assign(n + 1, vector<T>(m + 1, T{}));
        t3.assign(n + 1, vector<T>(m + 1, T{}));
        t4.assign(n + 1, vector<T>(m + 1, T{}));
    }
    void _add(int x, int y, const T &v)
    {
        for (int i = x; i <= n; i += i & -i)
            for (int j = y; j <= m; j += j & -j)
            {
                t1[i][j] += v;
                t2[i][j] += v * x;
                t3[i][j] += v * y;
                t4[i][j] += v * x * y;
            }
    }
    void rangeAdd(int x1, int y1, int x2, int y2, const T &v)
    {
        _add(x1, y1, v);
        _add(x1, y2 + 1, -v);
        _add(x2 + 1, y1, -v);
        _add(x2 + 1, y2 + 1, v);
    }
    T prefixSum(int x, int y)
    {
        T r{};
        for (int i = x; i > 0; i -= i & -i)
            for (int j = y; j > 0; j -= j & -j)
                r += t1[i][j] * (x + 1) * (y + 1) - t2[i][j] * (y + 1) - t3[i][j] * (x + 1) + t4[i][j];
        return r;
    }
    T rangeSum(int x1, int y1, int x2, int y2)
    {
        if (x1 > x2 || y1 > y2)
            return T{};
        return prefixSum(x2, y2) - prefixSum(x1 - 1, y2) - prefixSum(x2, y1 - 1) + prefixSum(x1 - 1, y1 - 1);
    }
};
struct Random
{
    mt19937_64 rng;
    Random() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}
    ull rand_ull(ull max_val = -1) { return rng() % (max_val + 1); }
    ll rand_ll(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
    int rand_int(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); }
    double rand_db(double l, double r) { return uniform_real_distribution<double>(l, r)(rng); }
    bool rand_bool(double p = 0.5) { return bernoulli_distribution(p)(rng); }
    template <typename T>
    void shuffle(vector<T> &v) { std::shuffle(v.begin(), v.end(), rng); }
};
ll qmi(ll a, ll b, ll p)
{
    ll res = 1 % p;
    a %= p;
    while (b)
    {
        if (b & 1)
            res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
/*

*/

ll n, len;
ll a[N], add[M];
vll tmp[M];
ll get(ll i)
{
    return (i - 1) / len + 1;
}

void build(ll block)
{
    ll st = (block - 1) * len + 1;
    ll ed = min(block * len, n);
    tmp[block].clear();
    rep(i, st, ed)
    {
        tmp[block].push_back(a[i]);
    }
    sort(all(tmp[block]));
}

void change(ll l, ll r, ll d)
{
    ll bl = get(l), br = get(r);
    if (bl == br)
    {
        rep(i, l, r) a[i] += d;
        build(bl);
    }
    else
    {
        rep(i, l, min(bl * len, n)) a[i] += d;
        build(bl);
        rep(i, (br - 1) * len + 1, r) a[i] += d;
        build(br);
        rep(i, bl + 1, br - 1) add[i] += d;
    }
}

ll query(ll l, ll r, ll c)
{
    ll bl = get(l), br = get(r);
    ll ans = -INF;
    if (bl == br)
    {
        rep(i, l, r)
        {
            if (a[i] + add[bl] < c)
                cmax(ans, a[i] + add[bl]);
        }
        if (ans == -INF)
            return -1;
        return ans;
    }
    else
    {
        rep(i, l, min(bl * len, n))
        {
            if (a[i] + add[bl] < c)
                cmax(ans, a[i] + add[bl]);
        }
        rep(i, (br - 1) * len + 1, r)
        {
            if (a[i] + add[br] < c)
                cmax(ans, a[i] + add[br]);
        }
        rep(i, bl + 1, br - 1)
        {
            ll d = c - add[i];
            ll num = lower_bound(all(tmp[i]), d) - tmp[i].begin();

            auto it = lower_bound(all(tmp[i]), d);
            if (it != tmp[i].begin())
            {
                it--;
                ll now = *it + add[i];
                if (now < c)
                {
                    cmax(ans, now);
                }
            }
        }
        if (ans == -INF)
            return -1;
        return ans;
    }
}
void solve()
{
    cin >> n;
    len = sqrt(n);
    ll cnt = get(n);
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, cnt)
    {
        add[i] = 0;
        build(i);
    }
    rep(i, 1, n)
    {
        ll op, l, r, c;
        cin >> op >> l >> r >> c;
        if (op == 0)
        {
            change(l, r, c);
        }
        else
        {
            ll ans = query(l, r, c);
            cout << ans << endl;
        }
    }
}

int main()
{
    IOS;

    int _ = 1;
    // cin>>_;//如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

数列分块入门4

P13979 数列分块入门 4

题目背景

洛谷的数列分块入门系列的测试数据范围和原题有不同。

题目描述

给出一个长为 $n$ 的数列,以及 $n$ 个操作,操作涉及区间加法,区间求和。

输入格式

第一行输入一个数字 $n$。

第二行输入 $n$ 个数字,第 $i$ 个数字为 $a_i$,以空格隔开。

接下来输入 $n$ 行询问,每行输入四个数字 $\mathrm{opt}$、$l$、$r$、$c$,以空格隔开。

若 $\mathrm{opt} = 0$,表示将位于 $[l, r]$ 的之间的数字都加 $c$。

若 $\mathrm{opt} = 1$,表示询问位于 $[l, r]$ 的所有数字的和 $\bmod (c+1)$。你需要输出非负的余数值

输出格式

对于每次询问,输出一行一个数字表示答案。

输入输出样例 #1

输入 #1

4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4

输出 #1

1
4

说明/提示

子任务

子任务 1(40 分):$1 \leq n \leq 50000, -2^{31} \leq a_i,c \leq 2^{31}-1$。

子任务 2(60 分):$1 \leq n \leq 300000, -2^{31} \leq a_i,c \leq 2^{31}-1$。

对于所有测试数据,满足 $1 \leq n \leq 300000, -2^{31} \leq a_i,c \leq 2^{31}-1$。$1 \leq l \leq r \leq n$。$\mathrm{opt} \in {0,1}, 1 \leq l \leq r\leq n$。每次操作后的 $a_i$ 满足 $-2^{31} \leq a_i \leq 2^{31}-1$。特别地,数据保证当 $\mathrm{opt}=1$ 时,$c\geq 0$。

先吐槽一下vjudge的评测系统,太水了,我很多边界和细节都没有注意,给我一次过了,现在果断换上洛谷的题面和评测,第一次在Vjudge上写还真以为会了呢,结果一大堆细节没有处理好,真是会让人产生学会了的幻觉啊!!!
代码:

#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 3e5 + 10, M = 550, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
template <typename T>
struct BIT1
{
    int n;
    vector<T> tr;
    BIT1(int n) : n(n), tr(n + 1) {}
    void add(int x, T v)
    {
        for (; x <= n; x += x & -x)
            tr[x] += v;
    }
    T sum(int x)
    {
        T r = 0;
        for (; x; x -= x & -x)
            r += tr[x];
        return r;
    }
    T range(int l, int r) { return sum(r) - sum(l - 1); }
};
template <typename T>
struct BIT2
{
    int n, m;
    vector<vector<T>> t1, t2, t3, t4;
    BIT2(int n_ = 0, int m_ = 0) { init(n_, m_); }
    void init(int n_, int m_)
    {
        n = n_;
        m = m_;
        t1.assign(n + 1, vector<T>(m + 1, T{}));
        t2.assign(n + 1, vector<T>(m + 1, T{}));
        t3.assign(n + 1, vector<T>(m + 1, T{}));
        t4.assign(n + 1, vector<T>(m + 1, T{}));
    }
    void _add(int x, int y, const T &v)
    {
        for (int i = x; i <= n; i += i & -i)
            for (int j = y; j <= m; j += j & -j)
            {
                t1[i][j] += v;
                t2[i][j] += v * x;
                t3[i][j] += v * y;
                t4[i][j] += v * x * y;
            }
    }
    void rangeAdd(int x1, int y1, int x2, int y2, const T &v)
    {
        _add(x1, y1, v);
        _add(x1, y2 + 1, -v);
        _add(x2 + 1, y1, -v);
        _add(x2 + 1, y2 + 1, v);
    }
    T prefixSum(int x, int y)
    {
        T r{};
        for (int i = x; i > 0; i -= i & -i)
            for (int j = y; j > 0; j -= j & -j)
                r += t1[i][j] * (x + 1) * (y + 1) - t2[i][j] * (y + 1) - t3[i][j] * (x + 1) + t4[i][j];
        return r;
    }
    T rangeSum(int x1, int y1, int x2, int y2)
    {
        if (x1 > x2 || y1 > y2)
            return T{};
        return prefixSum(x2, y2) - prefixSum(x1 - 1, y2) - prefixSum(x2, y1 - 1) + prefixSum(x1 - 1, y1 - 1);
    }
};
struct Random
{
    mt19937_64 rng;
    Random() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}
    ull rand_ull(ull max_val = -1) { return rng() % (max_val + 1); }
    ll rand_ll(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
    int rand_int(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); }
    double rand_db(double l, double r) { return uniform_real_distribution<double>(l, r)(rng); }
    bool rand_bool(double p = 0.5) { return bernoulli_distribution(p)(rng); }
    template <typename T>
    void shuffle(vector<T> &v) { std::shuffle(v.begin(), v.end(), rng); }
};
ll qmi(ll a, ll b, ll p)
{
    ll res = 1 % p;
    a %= p;
    while (b)
    {
        if (b & 1)
            res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
/*

*/

ll n, len;
ll a[N], add[M], sum[M];

ll get(ll i)
{
    return (i - 1) / len + 1;
}

void modify(ll l, ll r, ll d)
{
    ll bl = get(l), br = get(r);
    if (bl == br)
    {
        rep(i, l, r)
        {
            a[i] += d;
            sum[bl] += d;
        }
    }
    else
    {

        for (ll i = l; i <= min(bl * len, n); i++)
        {
            a[i] += d;
            sum[bl] += d;
        }

        for (ll i = (br - 1) * len + 1; i <= r; i++)
        {
            a[i] += d;
            sum[br] += d;
        }

        for (ll i = bl + 1; i < br; i++)
        {
            add[i] += d;
        }
    }
}

ll query(ll l, ll r, ll c)
{
    ll m = c + 1;
    ll tot = 0;
    ll bl = get(l), br = get(r);

    if (bl == br)
    {
        rep(i, l, r)
        {
            tot = (tot + a[i] + add[bl]);
        }
    }
    else
    {

        for (ll i = l; i <= min(bl * len, n); i++)
        {
            tot = (tot + a[i] + add[bl]);
        }

        for (ll i = (br - 1) * len + 1; i <= r; i++)
        {
            tot = (tot + a[i] + add[br]);
        }

        for (ll i = bl + 1; i < br; i++)
        {

            ll st = (i - 1) * len + 1;
            ll ed = min(i * len, n);
            ll far = ed - st + 1;
            tot += sum[i] + add[i] * far;
        }
    }

    return mod(tot, m);
}

void solve()
{
    cin >> n;
    len = sqrt(n);

    // mem(add, 0);
    // mem(sum, 0);

    rep(i, 1, n)
    {
        cin >> a[i];
        sum[get(i)] += a[i];
    }

    rep(i, 1, n)
    {
        ll op, l, r, c;
        cin >> op >> l >> r >> c;
        if (op == 0)
        {
            modify(l, r, c);
        }
        else
        {
            ll ans = query(l, r, c);
            cout << ans << endl;
        }
    }
}

int main()
{
    IOS;

    int _ = 1;
    // cin>>_;//如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

数列分块入门 5

P13980 数列分块入门 5

题目背景

洛谷的数列分块入门系列的测试数据范围和原题有不同。

题目描述

给出一个长为 $n$ 的数列 $a_1 \ldots a_n$,以及 $n$ 个操作,操作涉及区间开方,区间求和。

输入格式

第一行输入一个数字 $n$。

第二行输入 $n$ 个数字,第 $i$ 个数字为 $a_i$,以空格隔开。

接下来输入 $n$ 行询问,每行输入三个数字 $\mathrm{opt}, l, r$,以空格隔开。

若 $\mathrm{opt} = 0$,表示将位于 $[l, r]$ 的之间的数字都开方。对于区间中每个 $a_i(l\le i\le r),: a_i \leftarrow \left\lfloor \sqrt{a_i}\right\rfloor$

若 $\mathrm{opt} = 1$,表示询问位于 $[l, r]$ 的所有数字的和。

输出格式

对于每次询问,输出一行一个数字表示答案。

输入输出样例 #1

输入 #1

4
1 2 2 3
0 1 3
1 1 4
0 1 2
1 1 2

输出 #1

6
2

说明/提示

子任务

子任务 1(40 分):$1 \leq n \leq 50000, 0 \leq a_i,\mathrm{ans} \leq 2^{31}-1$。

子任务 2(60 分):$1 \leq n \leq 300000, 0 \leq a_i \leq 2^{31}-1$,$0\leq \mathrm{ans}\leq 2^{63}-1$。

对于所有测试数据,满足 $1 \leq n \leq 300000, 0 \leq a_i \leq 2^{31}-1$,$0\leq \mathrm{ans} \leq 2^{63}-1$。$1 \leq l \leq r \leq n$。$\mathrm{opt} \in {0,1}, 1 \leq l \leq r\leq n$。每次操作后的 $a_i$ 满足 $0 \leq a_i \leq 2^{31}-1$。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 3e5 + 10, M = 550;

ll n, len;
ll a[N], sum[M];  // sum记录每个块的和
bool flag[M];     // flag标记块是否全为0或1(开方后不再变化)

ll get(ll i) {
    return (i - 1) / len + 1;
}

void build(ll block) {
    ll st = (block - 1) * len + 1;
    ll ed = min(block * len, n);
    sum[block] = 0;
    flag[block] = true;  
    
    for (ll i = st; i <= ed; i++) {
        sum[block] += a[i];
        if (a[i] > 1) {
            flag[block] = false;  
        }
    }
}


void sqrt_range(ll l, ll r) {
    ll bl = get(l), br = get(r);
    
    if (bl == br) {
        if (flag[bl]) return; 
        
        for (ll i = l; i <= r; i++) {
            ll old = a[i];
            a[i] = (ll)sqrt(a[i]);  
            sum[bl] += (a[i] - old);
        }
        
        flag[bl] = true;
        ll st = (bl - 1) * len + 1;
        ll ed = min(bl * len, n);
        for (ll i = st; i <= ed; i++) {
            if (a[i] > 1) {
                flag[bl] = false;
                break;
            }
        }
    } else {
       
        if (!flag[bl]) {
            for (ll i = l; i <= bl * len; i++) {
                ll old = a[i];
                a[i] = (ll)sqrt(a[i]);
                sum[bl] += (a[i] - old);
            }
           
            flag[bl] = true;
            ll st = (bl - 1) * len + 1;
            ll ed = bl * len;
            for (ll i = st; i <= ed; i++) {
                if (a[i] > 1) {
                    flag[bl] = false;
                    break;
                }
            }
        }
        
    
        if (!flag[br]) {
            for (ll i = (br - 1) * len + 1; i <= r; i++) {
                ll old = a[i];
                a[i] = (ll)sqrt(a[i]);
                sum[br] += (a[i] - old);
            }
          
            flag[br] = true;
            ll st = (br - 1) * len + 1;
            ll ed = min(br * len, n);
            for (ll i = st; i <= ed; i++) {
                if (a[i] > 1) {
                    flag[br] = false;
                    break;
                }
            }
        }
        
       
        for (ll i = bl + 1; i <= br - 1; i++) {
            if (flag[i]) continue; 
            
            flag[i] = true;  
            ll st = (i - 1) * len + 1;
            ll ed = min(i * len, n);
            
            for (ll j = st; j <= ed; j++) {
                ll old = a[j];
                a[j] = (ll)sqrt(a[j]);
                sum[i] += (a[j] - old);
                if (a[j] > 1) {
                    flag[i] = false;  
                }
            }
        }
    }
}


ll query_sum(ll l, ll r) {
    ll bl = get(l), br = get(r);
    ll tot = 0;
    
    if (bl == br) {
        for (ll i = l; i <= r; i++) {
            tot += a[i];
        }
    } else {
       
        for (ll i = l; i <= bl * len; i++) {
            tot += a[i];
        }
        
        for (ll i = (br - 1) * len + 1; i <= r; i++) {
            tot += a[i];
        }
       
        for (ll i = bl + 1; i <= br - 1; i++) {
            tot += sum[i];
        }
    }
    return tot;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    cin >> n;
    len = sqrt(n);
    ll blocks = get(n);
    
    for (ll i = 1; i <= n; i++) {
        cin >> a[i];
    }
    

    for (ll i = 1; i <= blocks; i++) {
        build(i);
    }
    
    for (ll i = 1; i <= n; i++) {
        ll op, l, r;
        cin >> op >> l >> r ;
        if (op == 0) {
         
            sqrt_range(l, r);
        } else {
        
            ll result = query_sum(l, r);
            cout << result << endl;
        }
    }
    
    return 0;
}