分块二分——BZO3343 教主的魔法
2017-12-12 15:54
120 查看
题面:BZOJ3343
分块二分大暴力!
以前初三刚学分块的时候以为这题很难QAQ,现在认为……
这题实在是water到不知道哪里去了666
我们对于数据分块,然后对块内的数进行排序
修改的时候发现如果整个块都被覆盖在区间里面的话,那么就对整个块进行标记(因为整个块内的数都被加上了)
两边多出来的暴力修改,然后再次对块内进行排序
排序的原因是询问时要对块进行二分
询问还是老办法,对于一整个块的数据我们二分找比要求的数大的个数(这就是排序的原因),对于多出来的暴力统计
时间复杂度大约是O(Qn√∗logn)
分块二分大暴力!
以前初三刚学分块的时候以为这题很难QAQ,现在认为……
这题实在是water到不知道哪里去了666
我们对于数据分块,然后对块内的数进行排序
修改的时候发现如果整个块都被覆盖在区间里面的话,那么就对整个块进行标记(因为整个块内的数都被加上了)
两边多出来的暴力修改,然后再次对块内进行排序
排序的原因是询问时要对块进行二分
询问还是老办法,对于一整个块的数据我们二分找比要求的数大的个数(这就是排序的原因),对于多出来的暴力统计
时间复杂度大约是O(Qn√∗logn)
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <iostream> #include <ctime> #include <map> #include <queue> #include <cstdlib> #include <string> #include <climits> #include <set> #include <vector> using namespace std; inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f; } inline void write(int x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10);putchar(x%10+'0'); } inline void writeln(int x){ write(x);puts(""); } int n,m,c,p,a[1000001],w[1000001]={0},b[1000001]={0},sum[1000001]={0}; inline void yu(int x){ int l=(x-1)*p+1,r=min(n,x*p); for(int i=l;i<=r;i++)b[i]=a[i]; sort(b+l,b+r+1); } inline void add(int x,int y,int z){ if(w[x]==w[y])for(int i=x;i<=y;i++)a[i]+=z; else{ for(int i=x;i<=w[x]*p;i++)a[i]+=z; for(int i=(w[y]-1)*p+1;i<=y;i++)a[i]+=z; } yu(w[x]);yu(w[y]); for(int i=w[x]+1;i<w[y];i++)sum[i]+=z; } inline int erfen(int x,int v){ int l=(x-1)*p+1,r=min(n,x*p);int la=r; while(l<=r){ int mm=(l+r)/2; if(b[mm]<v)l=mm+1; else r=mm-1; } return la-l+1; } inline int ssum(int x,int y,int z){ int ans=0; if(w[x]==w[y]){for(int i=x;i<=y;i++)if(a[i]+sum[w[i]]>=z)ans++;} else{ for(int i=x;i<=w[x]*p;i++)if(a[i]+sum[w[i]]>=z)ans++; for(int i=(w[y]-1)*p+1;i<=y;i++)if(a[i]+sum[w[i]]>=z)ans++; } for(int i=w[x]+1;i<w[y];i++)ans+=erfen(i,z-sum[i]); return ans; } int main() { n=read();c=read(); p=(int)(sqrt(n)); for(< d801 span class="hljs-keyword">int i=1;i<=n;i++){ a[i]=read(); w[i]=(i-1)/p+1; b[i]=a[i]; } if(n%p==0)m=n/p; else m=n/p+1; for(int i=1;i<=m;i++)yu(i); for(int i=1;i<=c;i++){ char ss[5];scanf("%s",ss);int x=read(),y=read(),z=read(); if(ss[0]=='M')add(x,y,z); else writeln(ssum(x,y,z)); } return 0; }
相关文章推荐
- BZOJ_3343_教主的魔法_分块+二分查找
- bzoj3342 教主的魔法(分块+二分查找)
- BZOJ[3343]教主的魔法 分块+二分
- bzoj3343 教主的魔法 ( 分块 +二分)
- [BZOJ]3343: 教主的魔法 分块+二分
- Bzoj 3343: 教主的魔法(分块+二分答案)
- [bzoj3343]&&[洛谷2810] [分块][块内排序][二分查找]教主的魔法
- 【bzoj3343】教主的魔法 分块+二分
- 洛谷.2801.教主的魔法(分块 二分)
- Bzoj 3343: 教主的魔法 分块,二分
- BZOJ 3343: 教主的魔法(分块+二分查找)
- [luoguP2801] 教主的魔法(二分 + 分块)
- [bzoj3343]教主的魔法 分块
- 【bzoj3343】教主的魔法
- 51NOD 1640 天气晴朗的魔法(二分+最大生成树)
- 【bzoj3343】教主的魔法
- bzoj千题计划154:bzoj3343: 教主的魔法
- 洛谷 P2801 教主的魔法
- 【BZOJ】【P3343】【教主的魔法】【题解】【分块】
- 教主的魔法