BZOJ 3343 教主的魔法(分块)
题意:
有一个1e6的数组,t次操作:将[l,r]内的值增加w,或者查询[l,r]内的值大于等于add的
思路:
分块,块大小为sqrt(n),每次只需要暴力头尾两块,中间的整块打标记,
对于查询查操作,块内排序然后二分即可
复杂度O(T(sqrt(n)+sqrt(n)logn))
代码:
可以弄两个数组对应着写,会比我这样stl乱写快一倍
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 //#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 1e6+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; //const db pi = acos(-1.0); struct node{ int id; ll v; }; int n, q; vector<node>blc[maxn]; int block; bool cmp(node a, node b){ return a.v<b.v; } ll add[maxn]; int main(){ scanf("%d %d", &n, &q); int block = (int)sqrt(n); for(int i = 0; i < n; i++){ node tmp; tmp.id = i; scanf("%lld", &tmp.v); blc[i/block].pb(tmp); } for(int i = 0; i <= (n-1)/block; i++){ sort(blc[i].begin(), blc[i].end(), cmp); } while(q--){ char op[3]; int x, y; ll w; scanf("%s",op+1); scanf("%d %d %lld", &x, &y, &w); x--;y--; int bx = x/block; int by = y/block; if(op[1]=='M'){ if(bx==by){ for(int i = 0; i < (int)blc[bx].size(); i++){ node a = blc[bx][i]; if(a.id>=x&&a.id<=y)blc[bx][i].v+=w; } sort(blc[bx].begin(), blc[bx].end(),cmp); } else{ int rx = min(n-1, (bx+1)*block-1); int ly = by*block; for(int i = 0; i < (int)blc[bx].size(); i++){ int id = blc[bx][i].id; if(id>=x&&id<=y)blc[bx][i].v+=w; }sort(blc[bx].begin(), blc[bx].end(),cmp); for(int i = 0; i < (int)blc[by].size(); i++){ int id = blc[by][i].id; if(id>=x&&id<=y)blc[by][i].v+=w; }sort(blc[by].begin(), blc[by].end(),cmp); for(int i = bx+1; i < by; i++){ add[i]+=w; } } } else{ int ans = 0; if(bx==by){ for(int i = 0; i < (int)blc[bx].size(); i++){ int id = blc[bx][i].id; if(id>=x&&id<=y&&blc[bx][i].v+add[bx]>=w)ans++; } } else{ for(int i = 0; i < (int)blc[bx].size(); i++){ int id = blc[bx][i].id; if(id>=x&&id<=y&&blc[bx][i].v+add[bx]>=w)ans++; } for(int i = 0; i < (int)blc[by].size(); i++){ int id = blc[by][i].id; if(id>=x&&id<=y&&blc[by][i].v+add[by]>=w)ans++; } //printf("--%d\n",ans); for(int i = bx+1; i < by; i++){ ll x = w-add[i]; int l = 0; int r = block-1; int pos = block; while(l<=r){ int mid = (l+r)>>1; if(blc[i][mid].v>=x){ pos = mid; r = mid-1; } else l = mid+1; } ans+=block-pos; } } printf("%d\n",ans); } } return 0; } /* 5 3 1 2 3 4 5 A 1 5 4 M 3 5 1 A 1 5 4 5 7 3 1 4 2 5 A 1 5 4 M 3 5 1 M 3 5 2 A 1 5 4 M 1 1 3 A 1 5 4 A 1 5 10 5 3 3 1 4 2 5 A 1 5 10 M 1 5 2 A 1 5 10 */