首页 > 代码库 > BZOJ3343 教主的魔法 二分法+分块
BZOJ3343 教主的魔法 二分法+分块
题意:给定一个数列,维护:1、[L,R]之间所有的数+=W 2、求[L,R]中大于等于C的数的数量
题解:更新用add标记,头尾俩块暴力重构;查询将每个块排序然后二分找。
#include <cmath>#include <ctime>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;const int MAXS=1000+2;struct BLOCK{ int a[MAXS],b[MAXS],add;}block[MAXS];int N,M,S;char s;void Update(int l,int r,int x){ if((l-1)%S){ int p=(l-1)/S+1; for(int i=l-S*(p-1);i<=S && i<=r-(p-1)*S;i++) block[p].a[i]+=x; for(int i=1;i<=S;i++) block[p].b[i]=block[p].a[i]; sort(block[p].b+1,block[p].b+S+1); l=p*S+1; } while(l+S-1<=r) block[l/S+1].add+=x,l+=S; if(r%S){ int p=l/S+1;r-=S*(p-1); for(int i=1;i<=r;i++) block[p].a[i]+=x; for(int i=1;i<=S;i++) block[p].b[i]=block[p].a[i]; sort(block[p].b+1,block[p].b+S+1); }}int Find(int p,int l,int r,int c){ c-=block[p].add; int m=(l+r)>>1; while(l<=r){ if(block[p].b[m]<c) l=m+1; else r=m-1; m=(l+r)>>1; } return S-l+1;}int Query(int l,int r,int c){ int ret=0; if((l-1)%S){ int p=(l-1)/S+1; for(int i=l-S*(p-1);i<=r-S*(p-1) && i<=S;i++) if(block[p].a[i]>=c-block[p].add) ret++; l=p*S+1; } while(l+S-1<=r) ret+=Find(l/S+1,1,S,c),l+=S; if(r%S){ int p=l/S+1; for(int i=1;i<=r-S*(p-1);i++) if(block[p].a[i]>=c-block[p].add) ret++; } return ret;}int main(){ memset(block,0X7F,sizeof(block)); block[1].add=0; cin >> N >> M,S=(int)sqrt(N); for(int i=1,j=1,k=1;i<=N;i++,j++){ cin >> block[k].a[j],block[k].b[j]=block[k].a[j]; if(j==S || i==N){ sort(block[k].b+1,block[k].b+j+1); k++,j=0,block[k].add=0; } } N=(N%S?N/S+1:N/S); for(int i=1,l,r,x;i<=M;i++){ cin >> s; cin >> l >> r >> x; if(s==‘M‘) Update(l,r,x); if(s==‘A‘) cout << Query(l,r,x) << endl; } return 0;}
BZOJ3343 教主的魔法 二分法+分块
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。