1、分块 (区间加法,查询小于x的个数)
技巧:开vector对区间sort,注意每次暴力更新的区间需要重新把数据放入vector中。
#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; }
2、区间加法,区间查询
开两个标记数组,一个是sum数组,一个是add数组。
#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; }
3、区间开方,区间查询
由于每个数开方的次数不多,所以暴力去开方就行了,分块记录区间中为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; }
原文:https://www.cnblogs.com/ckxkexing/p/10300122.html