[模板] 分块

区间修改+单点查询

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define MAXN 100005

int drop[MAXN],tag[MAXN];
int N,M;

int main() {

    cin >> N;
    for(int i=0;i<N;++i) cin >> drop[i];
    int block = sqrt(N);

    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c; l--; r--;
        if(op==1) cout << drop[r]+tag[r/block] << '\n';
        else {
            for(;l<=r&&l%block;++l) drop[l] += c;
            for(;l+block-1<=r;l+=block) tag[l/block] += c;
            for(;l<=r;++l) drop[l] += c;
        }
    }
    return 0;
}

区间修改+统计区间小于\(c^2\)的数总量

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 100005
vector<int> arr[MAXN];
int drop[MAXN],tag[MAXN];
int N,M,block;

inline void reset(int k) {
    arr[k].clear();
    for(int i=k*block;i<=min(N-1,(k+1)*block-1);++i) 
        arr[k].push_back(drop[i]);
    sort(arr[k].begin(),arr[k].end());
}

int main() {

    cin >> N; block = sqrt(N);
    for(int i=0;i<N;++i) {
        cin >> drop[i]; arr[i/block].push_back(drop[i]);
    }
    for(int i=0;i<=(N-1)/block;++i) sort(arr[i].begin(),arr[i].end());

    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c; l--; r--;
        if(op==0) {
            int ll = l;
            for(;l<=r&&l%block;++l) drop[l] += c;
            for(;l+block-1<=r;l+=block) tag[l/block] += c;
            for(;l<=r;++l) drop[l] += c;
            reset(ll/block); reset(r/block);
        }
        else {
            int ans = 0; c *= c;
            for(;l<=r&&l%block;++l) ans += drop[l]+tag[l/block]<c ? 1 : 0;
            for(;l+block-1<=r;l+=block) ans += lower_bound(arr[l/block].begin(),arr[l/block].end(),c-tag[l/block]) - arr[l/block].begin();
            for(;l<=r;++l) ans += drop[l]+tag[l/block]<c ? 1 : 0;
            cout << ans << '\n';
        }
    }
    return 0;
}

区间修改+查询区间内c的前驱

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 100005
vector<int> arr[MAXN];
int drop[MAXN],tag[MAXN];
int N,M,block;

inline void reset(int k) {
    arr[k].clear();
    for(int i=k*block;i<=min(N-1,(k+1)*block-1);++i) 
        arr[k].push_back(drop[i]);
    sort(arr[k].begin(),arr[k].end());
}

int main() {

    cin >> N; block = sqrt(N);
    for(int i=0;i<N;++i) {
        cin >> drop[i]; arr[i/block].push_back(drop[i]);
    }
    for(int i=0;i<=(N-1)/block;++i) sort(arr[i].begin(),arr[i].end());

    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c; l--; r--;
        if(op==0) {
            int ll = l;
            for(;l<=r&&l%block;++l) drop[l] += c;
            for(;l+block-1<=r;l+=block) tag[l/block] += c;
            for(;l<=r;++l) drop[l] += c;
            reset(ll/block); reset(r/block);
        }
        else {
            int ans = -1;
            for(;l<=r&&l%block;++l) 
                if(drop[l]+tag[l/block]<c) ans = max(ans,drop[l]+tag[l/block]);
            for(;l+block-1<=r;l+=block) {
                int tmp = lower_bound(arr[l/block].begin(),arr[l/block].end(),c-tag[l/block]) - arr[l/block].begin();
                if(tmp) ans = max(ans,arr[l/block][tmp-1]+tag[l/block]);
            }
            for(;l<=r;++l) 
                if(drop[l]+tag[l/block]<c) ans = max(ans,drop[l]+tag[l/block]);
            cout << ans << '\n';
        }
    }
    return 0;
}

区间修改+区间求和

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#define MAXN 100005
using namespace std;
int drop[MAXN],tag[MAXN],sum[MAXN];
int N,M,block;
int main() {

    cin >> N; block = sqrt(N);
    for(int i=0;i<N;++i) {
        cin >> drop[i]; sum[i/block] += drop[i];
    }

    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c; l--; r--;
        if(op==0) {
            for(;l<=r&&l%block;++l) drop[l] += c,sum[l/block] += c;
            for(;l+block-1<=r;l+=block) tag[l/block] += c;
            for(;l<=r;++l) drop[l] += c,sum[l/block] += c;
        }
        else {
            long long ans = 0;
            for(;l<=r&&l%block;++l) ans += drop[l] + tag[l/block];
            for(;l+block-1<=r;l+=block) ans += sum[l/block] + (long long)block*tag[l/block];
            for(;l<=r;++l) ans += drop[l] + tag[l/block];
            cout << ans%(c+1) << '\n';
        }
    }
    return 0;
}

区间开方+区间求和

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#define MAXN 100005
using namespace std;
int drop[MAXN],tag[MAXN],sum[MAXN];
int N,M,block;

inline void solve(int k) {
    if(tag[k]) return;
    tag[k] = 1;
    for(int i=k*block;i<=min(N-1,(k+1)*block-1);++i) {
        if(drop[i]==1) continue;
        sum[k] -= drop[i]; drop[i] = sqrt(drop[i]); sum[k] += drop[i];
        tag[k] = 0;
    }
}

int main() {

    cin >> N; block = sqrt(N);
    for(int i=0;i<N;++i) {
        cin >> drop[i]; sum[i/block] += drop[i];
    }

    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c; l--; r--;
        if(op==0) {
            for(;l<=r&&l%block;++l) sum[l/block] -= drop[l],drop[l] = sqrt(drop[l]),sum[l/block] += drop[l];
            for(;l+block-1<=r;l+=block) solve(l/block);
            for(;l<=r;++l) sum[l/block] -= drop[l],drop[l] = sqrt(drop[l]),sum[l/block] += drop[l];
        }
        else {
            long long ans = 0;
            for(;l<=r&&l%block;++l) ans += drop[l];
            for(;l+block-1<=r;l+=block) ans += sum[l/block];
            for(;l<=r;++l) ans += drop[l];
            cout << ans << '\n';
        }
    }
    return 0;
}

插入+单点查询

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <utility>
#define MAXN 200005
using namespace std;
int drop[MAXN],tot;
int N,M,block;

vector <int> vec[MAXN];

inline void rebuild() {
    int cnt = 0;
    for(int i=0;i<=(tot-1)/block;++i) {
        for(auto it:vec[i]) drop[cnt++] = it;
        vec[i].clear();
    }
    tot = cnt; block = sqrt(tot);
    for(int i=0;i<cnt;++i) vec[i/block].push_back(drop[i]);
}

inline pair<int,int> query(int pos) {
    int k = 0;
    while(pos>=(int)vec[k].size()) pos -= vec[k].size(),k++;
    return make_pair(k,pos);
}

inline void insert(int pos,int x) {
    pair<int,int> tmp = query(pos);
    vec[tmp.first].insert(vec[tmp.first].begin()+tmp.second,x);
    if((int)vec[tmp.first].size()>20*block) rebuild();
}

int main() {
    
    cin >> N; tot = N; block = sqrt(N);
    for(int i=0;i<N;++i) {
        int x; cin >> x; vec[i/block].push_back(x);
    }

    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c;
        if(op==0) insert(l-1,r); // put r in front of the l-th number
        else {
            pair<int,int> tmp = query(r-1);
            cout << vec[tmp.first][tmp.second] << '\n';
        }
    }
    return 0;
}

区间乘法加法+单点查询

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#define MAXN 100005
#define MOD 10007

using namespace std;
int drop[MAXN],add[MAXN],mul[MAXN];
int N,M,block;

inline void reset(int k) {
    for(int i=k*block;i<=min(N-1,block*(k+1)-1);++i) 
        drop[i] = (drop[i]*mul[k]+add[k])%MOD;
    add[k] = 0,mul[k] = 1;
}
int main() {

    cin >> N; block = sqrt(N);
    for(int i=0;i<N;++i) {
        cin >> drop[i]; mul[i/block] = 1;
    } 
    
    int op,l,r,c;
    for(int k=0;k<N;++k) {
        cin >> op >> l >> r >> c; l--; r--;
        if(op==2) cout << (drop[r]*mul[r/block]+add[r/block])%MOD << '\n';
        else {
            reset(l/block); reset(r/block);

            for(;l<=r&&l%block;++l) 
                if(op) drop[l] = (drop[l]*c)%MOD;
                else drop[l] = (drop[l]+c)%MOD;

            for(;l+block-1<=r;l+=block) {
                if(op) add[l/block] *= c,mul[l/block] *= c;
                else add[l/block] += c;
                add[l/block] %= MOD; mul[l/block] %= MOD;
            }

            for(;l<=r;++l)
                if(op) drop[l] = (drop[l]*c)%MOD;
                else drop[l] = (drop[l]+c)%MOD;
        }
    }
    return 0;
}

区间众数

#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <cmath>
using namespace std;

#define MAXN 100005
#define MAX_BLOCK 400

int N;
int block,cnt,tot = 0;
int dp[MAX_BLOCK][MAX_BLOCK],C[MAXN][MAX_BLOCK];
int book[MAXN],drop[MAXN],val[MAXN];
int L[MAX_BLOCK],R[MAX_BLOCK];

map <int,int> mp;

inline void pre(int k) {
	memset(book,0,sizeof(book));
	int maxx = -2147483648,cur = L[k];
	for(int i=k;i<=cnt;++i) {
		for(int j=L[i];j<=R[i];++j) {
			int t = ++ book[drop[j]];
			if(t>maxx||(t==maxx&&val[drop[j]]<val[cur])) {
				maxx = t; cur = drop[j];
			}
		}
		dp[k][i] = cur;
	}
}

inline void init() {
	
	block = sqrt(N);
	if(N%block) cnt = N/block+1;
	else cnt = N/block;

	for(int i=1;i<=cnt;++i) L[i] = (i-1)*block+1,R[i] = i*block;
	R[cnt] = N;

	for(int i=1;i<=cnt;++i) {
		pre(i);
		for(int j=1;j<=tot;++j) C[j][i] = C[j][i-1];
		for(int j=L[i];j<=R[i];++j) ++C[drop[j]][i];
	}
}

inline int query(int l,int r) {
	
	int maxx = -2147483648,cur = drop[l];
	int a = l/block+1, b = r/block+1;
	
	if(a==b||a+1==b) {
		for(int i=l;i<=r;++i) book[drop[i]] = 0;
		for(int i=l;i<=r;++i) {
			++book[drop[i]];
			if(book[drop[i]]>maxx||(book[drop[i]]==maxx&&val[drop[i]]<val[cur])) {
				maxx = book[drop[i]]; cur = drop[i];
			}
		}
		return cur;
	}

	cur = dp[a+1][b-1];
	maxx = C[cur][b-1] - C[cur][a];

	for(int i=l;i<=R[a];++i) book[drop[i]] = 0;
	for(int i=L[b];i<=r;++i) book[drop[i]] = 0;

	for(int i=l;i<=R[a];++i) {
		int c = ++book[drop[i]] + C[drop[i]][b-1] - C[drop[i]][a];
		if(c>maxx||(c==maxx&&val[drop[i]]<val[cur])) {
			maxx = c; cur = drop[i];		
		}
	}
	for(int i=L[b];i<=r;++i) {
		int c = ++book[drop[i]] + C[drop[i]][b-1] - C[drop[i]][a];
		if(c>maxx||(c==maxx&&val[drop[i]]<val[cur])) {
			maxx = c; cur = drop[i];		
		}
	}
	return cur;
}

int main() {

	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	//freopen("in.in","r",stdin);

	cin >> N; 
	for(int i=0;i<N;++i) {
		cin >> drop[i];
		if(mp[drop[i]]==0) val[++tot] = drop[i],mp[drop[i]] = tot;
		drop[i] = mp[drop[i]]; 
	}
	init();
	
	//for(int i=0;i<N;++i) {
		int l,r; cin >> l >> r;
		cout << val[query(l-1,r-1)] << '\n';
	//}

	return 0;
}
posted @ 2021-10-05 11:16  Neworld1111  阅读(50)  评论(0编辑  收藏  举报