分块笔记

1、分块 (区间加法,查询小于x的个数)

技巧:开vector对区间sort,注意每次暴力更新的区间需要重新把数据放入vector中。

https://loj.ac/problem/6278

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 50009;
            ll a[maxn];
            ll sum[maxn];
            vector<ll>s[1009];
            int belong[maxn];
int main(){
            int n;  scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
            int block = sqrt(n);
            int num = n/block; if(n%block) num++;
            for(int i=1; i<=n; i++)
            {
                belong[i] = (i-1)/block + 1;
                s[belong[i]].pb(a[i]);
            }
            for(int i=1; i<=num; i++) sort(s[i].begin(),s[i].end());
            int m = n;
            for(int i=1; i<=m; i++){
                int op;scanf("%d", &op);
                if(op == 0){
                    int l,r; ll x;
                    scanf("%d%d%lld", &l, &r, &x);

                     int id = belong[l],le = (belong[l]-1)*block+1;
                     if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++) a[i] += x;
                        s[id].clear();
                        for(int i=le; i<= belong[l]*block; i++) s[id].pb(a[i]);
                        sort(s[id].begin(),s[id].end());
                        continue;
                     }

                     for(int i=l; i<=belong[l]*block; i++) a[i] += x;
                     s[id].clear();
                     for(int i=le; i<= belong[l]*block; i++) s[id].pb(a[i]);
                     sort(s[id].begin(),s[id].end());

                     for(int i=belong[l]+1; i<=belong[r]-1; i++){
                        sum[i] += x;
                     }

                     int rid = belong[r],rle = (rid - 1) * block + 1;
                     for(int i=(rid-1)*block+1; i<=r; i++) a[i]+=x;
                     s[rid].clear();
                     for(int i=rle; i<=min(n, belong[r]*block) ; i++) s[rid].pb(a[i]);

                     sort(s[belong[r]].begin(),s[belong[r]].end());
                }
                else {
                        int l,r; ll x;
                        scanf("%d%d%lld", &l, &r, &x);
                        int cnt = 0;
                        if(belong[l] == belong[r]){
                            for(int i = l; i<= r; i++){
                                if(a[i] + sum[belong[i]] < 1ll*x*x) cnt++;
                            }
                        }
                        else {
                            for(int i=l; i<=belong[l]*block; i++)
                                if(a[i] + sum[belong[i]] < 1ll*x*x) cnt++;
                            for(int i=belong[l]+1; i<=belong[r]-1; i++){
                                cnt += lower_bound(s[i].begin(),s[i].end(), 1ll*x*x-sum[i]) - s[i].begin();
                            }
                            for(int i=(belong[r]-1)*block+1; i<=r; i++)
                                if(a[i] + sum[belong[i]] < 1ll*x*x) cnt++;
                        }
                        printf("%d\n", cnt);
                }
            }
            return 0;
}
View Code

2、区间加法,区间查询

开两个标记数组,一个是sum数组,一个是add数组。

https://loj.ac/problem/6280

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 50009;
            ll a[maxn];
            ll sum[maxn];
            ll add[maxn];
            int belong[maxn];
int main(){
            int n;  scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
            int block = sqrt(n);

            for(int i=1; i<=n; i++)
            {
                belong[i] = (i-1)/block + 1;
                sum[belong[i]] += a[i];
            }

            int m = n;
            while(m--){
                int op; scanf("%d", &op);
                if(op == 0){
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                    if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++){
                            a[i] += x;

                            sum[belong[i]] += x;
                        }
                        continue;
                    }
                    for(int i=l; i <= belong[l]*block; i++){
                        a[i] += x;
                        sum[belong[i]] += x;
                    }
                    for(int i=belong[l]+1; i<=belong[r]-1; i++){
                        sum[i] += block * x;
                        add[i] += x;
                    }
                    for(int i=(belong[r]-1) * block + 1; i<=r; i++){
                        a[i]+=x;
                        sum[belong[i]] += x;
                    }
                }
                else {
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                    ll ans = 0;
                    if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++){
                            ans = (ans + a[i] + add[belong[l]])%(x+1);
                        }
                    }
                    else {
                        for(int i=l; i <= belong[l]*block; i++){
                            ans = (ans + a[i] + add[belong[i]])%(x+1);
                        }
                        for(int i=belong[l]+1; i<=belong[r]-1; i++){
                            ans = (ans + sum[i])%(x+1);
                        }
                        for(int i=(belong[r]-1) * block + 1; i<=r; i++){
                            ans = (ans + a[i] + add[belong[i]]) %(x+1);
                        }
                    }
                    printf("%lld\n", ans);
                }

            }
            return 0;
}
View Code

3、区间开方,区间查询

https://loj.ac/problem/6281

由于每个数开方的次数不多,所以暴力去开方就行了,分块记录区间中为0,或1的个数。

这里 变化sum最好写成

sum[belong[i]] -= a[i];
a[i] = sqrt(a[i]);
sum[belong[i]]+=a[i];

/*
int tp = a[j] - sqrt(a[j]);
a[j] = sqrt(a[j]);
sum[belong[j]]-=tp;
*/

上面这个可能有精度问题

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 50009;
            ll a[maxn];
            ll tot[maxn],sum[maxn];
            int belong[maxn];
int main(){
            int n;  scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
            int block = sqrt(n);

            for(int i=1; i<=n; i++){
                belong[i] = (i-1)/block + 1;
                sum[belong[i]] += a[i];
                if(a[i] == 1 || a[i] == 0) {
                     tot[belong[i]]++;
                }
            }
            int m = n;

            while(m--){
                int op; scanf("%d", &op);
                if(op == 0){
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                    
                    
                    if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++){
                            if(a[i] == 1 || a[i] == 0) {
                                    continue;
                            }
                            sum[belong[i]] -= a[i];
                            a[i] = sqrt(a[i]);
                            sum[belong[i]]+=a[i];
                            if(a[i] == 1 || a[i] == 0) {
                                    tot[belong[i]]++;
                            }
                        }
                    }
                    else {
                        for(int i=l; i<=belong[l]*block; i++){
                            if(a[i] <= 1) continue;
                             sum[belong[i]] -= a[i];
                            a[i] = sqrt(a[i]);
                            sum[belong[i]]+=a[i];
                            if(a[i] == 1 || a[i] == 0) {
                                    tot[belong[i]]++;
                            }
                        }
                        for(int i=belong[l] + 1; i< belong[r]; i++){
                            if(tot[i] == block)continue;
                            for(int j=(i-1)*block+1; j<=i*block; j++){
                                if(a[j] <= 1) continue;
                                sum[belong[j]] -= a[j];
                                a[j] = sqrt(a[j]);
                                sum[belong[j]]+=a[j];
                            
                                if(a[j] == 1 || a[j] == 0) {
                                        tot[belong[j]]++;
                                }
                            }
                        }
                        for(int i=(belong[r]-1)*block+1; i<=r; i++){
                            if(a[i] <= 1) continue;
                            sum[belong[i]] -= a[i];
                            a[i] = sqrt(a[i]);
                            sum[belong[i]]+=a[i];
                            
                            if(a[i] == 1 || a[i] == 0) {
                                    tot[belong[i]]++;
                            }
                        }
                    }
                }
                else {
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                       r = min(r, n);
                    ll res = 0;
                    if(belong[l] == belong[r]) {
                        for(int i=l; i<=r; i++){
                            res += a[i];
                        }
                    }
                    else {
                        for(int i=l; i<=belong[l]*block; i++){
                            res += a[i];
                        }
                        for(int i=belong[l] + 1; i< belong[r]; i++){
                                res += sum[i];
                        }
                        for(int i=(belong[r]-1)*block+1; i<=r; i++){
                            res += a[i];
                        }
                    }
                    printf("%lld\n", res);
                }
            }

            return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/ckxkexing/p/10300122.html
今日推荐