zoukankan      html  css  js  c++  java
  • 20201110Day2 分块

    1 分块1

    区间加法,单点查询。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e4+10;
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,B;
    int query(int q){return a[q]+tag[belong[q]];}
    void change(int l,int r,int c){
    	int bl=belong[l]+1,br=belong[r]-1;
    	if(belong[l]==belong[r]) for(int i=l;i<=r;i++) a[i]+=c;
    	else{
    		for(int i=bl;i<=br;i++) tag[i]+=c;
    		for(int i=l;belong[i]!=bl;i++) a[i]+=c;
    		for(int i=r;belong[i]!=br;i--) a[i]+=c;
    	}
    	return ;
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
    	int t=n;
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(!w) change(b,c,d);
    		else printf("%lld
    ",query(c));
    	}
    	return 0;
    }
    
    

    2 分块2

    区间加法,查询区间内小于(c^2)的值的个数。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e4+10;
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,B;
    vector<int> v[505];
    void update(int b){
    	v[b].clear();
    	for(int i=(b-1)*B+1;belong[i]==b;i++) v[b].push_back(a[i]);
    	sort(v[b].begin(),v[b].end());
    }
    void change(int l,int r,int c){
    	int bl=belong[l]+1,br=belong[r]-1;
    	if(belong[l]==belong[r]){
    		for(int i=l;i<=r;i++) a[i]+=c;
    		update(belong[l]);
    	} 
    	else{
    		for(int i=bl;i<=br;i++) tag[i]+=c;
    		for(int i=l;belong[l]==belong[i];i++) a[i]+=c;
    		update(belong[l]);
    		for(int i=r;belong[i]==belong[r];i--) a[i]+=c;
    		update(belong[r]);
    	}
    }
    int query(int l,int r,int c){
    	int res=0,bl=belong[l]+1,br=belong[r]-1;
    	if(belong[l]==belong[r]){
    		for(int i=l;i<=r;i++) res+=(a[i]<c-tag[belong[l]]);
    		return res;
    	}
    	for(int i=bl;i<=br;i++) res+=lower_bound(v[i].begin(),v[i].end(),c-tag[i])-v[i].begin();
    	for(int i=l;belong[i]==belong[l];i++) res+=(a[i]<c-tag[belong[l]]);
    	for(int i=r;belong[i]==belong[r];i--) res+=(a[i]<c-tag[belong[r]]);
    	return res;
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,v[belong[i]].push_back(a[i]);
    	int t=n;
    	int mb=belong[n];
    	for(int i=1;i<=mb;i++) sort(v[i].begin(),v[i].end());
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(!w) change(b,c,d);
    		else d*=d,printf("%lld
    ",query(b,c,d));
    	}
    	return 0;
    }
    
    

    3 分块3

    区间加法,求区间某个点的前驱(在他之前小于该点的最大值,没有输出-1)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <set>
    using namespace std;
    const int maxn=5e5+10;
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,B;
    vector<int>que[1005];
    void init(){
    	for(int i=1;i<=belong[n];i++) sort(que[i].begin(),que[i].end());
    }
    void update(int x){
    	que[x].clear();
    	for(int i=(x-1)*B+1;belong[i]==x;i++) que[x].push_back(a[i]);
    	sort(que[x].begin(),que[x].end());
    }
    void modify(int l,int r,int c){
    	int bl=belong[l]+1,br=belong[r]-1;
    	if(belong[l]==belong[r]){
    		for(int i=l;i<=r;i++) a[i]+=c;
    		update(belong[l]);
    		return ;
    	}
    	for(int i=l;belong[l]==belong[i];i++) a[i]+=c;
    	for(int i=bl;i<=br;i++) tag[i]+=c;
    	for(int i=r;belong[i]==belong[r];i--) a[i]+=c;
    	update(belong[l]),update(belong[r]);
    }
    int find(int a,int c){
    	vector<int>::iterator it=lower_bound(que[a].begin(),que[a].end(),c-tag[a]);
    	if(it==que[a].begin()) return -1;
    	else {--it;return *it+tag[a];}
    }
    int query(int l,int r,int c){
    	int res=-1;
    	int bl=belong[l]+1,br=belong[r]-1;
    	if(belong[l]==belong[r]){
    		for(int i=l;i<=r;i++) if(a[i]+tag[belong[l]]<c) res=max(res,a[i]+tag[belong[l]]);
    		return res;
    	}
    	for(int i=bl;i<=br;i++) res=max(res,find(i,c));
    	for(int i=l;belong[l]==belong[i];i++) if(a[i]+tag[belong[l]]<c) res=max(res,a[i]+tag[belong[l]]);
    	for(int i=r;belong[r]==belong[i];i--) if(a[i]+tag[belong[r]]<c) res=max(res,a[i]+tag[belong[r]]);
    	return res;
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,que[belong[i]].push_back(a[i]);
    	int t=n;
    	init();
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(!w) modify(b,c,d);
    		else printf("%lld
    ",query(b,c,d));
    	}
    	return 0;
    }
    

    分块4

    区间加法,区间求和。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e5+10;
    int sum[maxn];
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,B;
    void add(int l,int r,int c){
    	int bl=belong[l]+1,br=belong[r]-1;
    	for(int i=l;i<=min(belong[l]*B,r);i++) a[i]+=c,sum[belong[i]]+=c;
    	if(belong[l]!=belong[r]){
    		for(int i=r;i>=(belong[r]-1)*B+1;i--) a[i]+=c,sum[belong[i]]+=c;
    	}
    	for(int i=bl;i<=br;i++) tag[i]+=c;
    }
    int query(int l,int r){
    	int ans=0;
    	int bl=belong[l]+1,br=belong[r]-1;
    	for(int i=l;i<=min(belong[l]*B,r);i++) ans+=a[i]+tag[belong[i]];
    	if(belong[l]!=belong[r]){
    		for(int i=r;i>=(belong[r]-1)*B+1;i--) ans+=a[i]+tag[belong[i]];
    	}
    	for(int i=bl;i<=br;i++) ans+=sum[i]+B*tag[i];
    	return ans;
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,sum[belong[i]]+=a[i];
    	int t=n;
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(!w) add(b,c,d);
    		else printf("%lld
    ",query(b,c)%(d+1));
    	}
    	return 0;
    }
    

    5 分块5

    区间求和,区间元素开根号(下取整)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e5+10;
    int sum[maxn];
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,B;
    int flag[maxn];
    void solve_sqrt(int x){
    	if(flag[x]) return ;
    	flag[x]=1;
    	sum[x]=0;
    	for(int i=(x-1)*B+1;i<=B*x;i++){
    		a[i]=sqrt(a[i]),sum[x]+=a[i];
    		if(a[i]>1) flag[x]=0;
    	}
    }
    void add(int l,int r,int c){
    	int bl=belong[l]+1,br=belong[r]-1;
    	for(int i=l;i<=min(belong[l]*B,r);i++) sum[belong[l]]-=a[i],a[i]=sqrt(a[i]),sum[belong[l]]+=a[i];
    	if(belong[l]!=belong[r]){
    		for(int i=r;i>=(belong[r]-1)*B+1;i--) sum[belong[r]]-=a[i],a[i]=sqrt(a[i]),sum[belong[i]]+=a[i];
    	}
    	for(int i=bl;i<=br;i++) solve_sqrt(i);
    }
    int query(int l,int r){
    	int ans=0;
    	int bl=belong[l]+1,br=belong[r]-1;
    	for(int i=l;i<=min(belong[l]*B,r);i++) ans+=a[i];
    	if(belong[l]!=belong[r]){
    		for(int i=r;i>=(belong[r]-1)*B+1;i--) ans+=a[i];
    	}
    	for(int i=bl;i<=br;i++) ans+=sum[i];
    	return ans;
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,sum[belong[i]]+=a[i];
    	int t=n;
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(!w) add(b,c,d);
    		else printf("%lld
    ",query(b,c));
    	}
    	return 0;
    }
    

    6 分块6

    单点插入,单点查询。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e5+10;
    int sum[maxn];
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,m,B;
    int flag[maxn];
    int st[maxn],top;
    vector<int> ve[maxn];
    pair<int,int> query(int b){
    	int x=1;
    	while(b>ve[x].size()) b-=ve[x].size(),x++;
    	return make_pair(x,b-1);
    }
    void rebuild(){
    	top=0;
    	for(int i=1;i<=m;i++){
    		for(vector<int>::iterator j=ve[i].begin();j!=ve[i].end();j++)
    			st[++top]=*j;
    		ve[i].clear();
    	}
    	int blo2=sqrt(top);
    	for(int i=1;i<=top;i++) ve[(i-1)/blo2+1].push_back(st[i]);
    	m=(top-1)/blo2+1;
    }
    void insertt(int a,int b){
    	pair<int,int> t=query(a);
    	ve[t.first].insert(ve[t.first].begin()+t.second,b);
    	if(ve[t.first].size()>20*B) rebuild();
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read();
    	for(int i=1;i<=n;i++) ve[(i-1)/B+1].push_back(a[i]);
    	m=(n-1)/B+1;
    	int t=n;
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(!w) insertt(b,c);
    		else{
    			pair<int,int> t=query(c);printf("%lld
    ",ve[t.first][t.second]);
    		}
    	}
    	return 0;
    }
    

    7 分块7

    区间加法,区间乘法,单点查询。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e5+10;
    const int mod=1e4+7;
    int sum[maxn];
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int addtag[maxn],multag[maxn],a[maxn],belong[maxn];
    int n,m,B;
    void reset(int x){
    	for(int i=(x-1)*B+1;i<=min(n,x*B);i++) a[i]=(a[i]*multag[x]+addtag[x])%mod;
    	addtag[x]=0,multag[x]=1;
    }	
    int query(int q){return (a[q]*multag[belong[q]]+addtag[belong[q]])%mod;}
    void add_change(int l,int r, int c){
    	reset(belong[l]);
    	int bl=belong[l]+1,br=belong[r]-1;
    	for(int i=l;i<=min(belong[l]*B,r);i++) a[i]+=c,a[i]%=mod;
    	if(belong[l]!=belong[r]){
    		reset(belong[r]);
    		for(int i=r;i>=(belong[r]-1)*B+1;i--) a[i]+=c,a[i]%=mod;
    	}
    	for(int i=bl;i<=br;i++) addtag[i]+=c,addtag[i]%=mod;
    }
    void mul_change(int l,int r,int c){
    	reset(belong[l]);
    	int bl=belong[l]+1,br=belong[r]-1;
    	for(int i=l;i<=min(belong[l]*B,r);i++) a[i]*=c,a[i]%=mod;
    	if(belong[l]!=belong[r]){
    		reset(belong[r]);
    		for(int i=r;i>=(belong[r]-1)*B+1;i--) a[i]*=c,a[i]%=mod;
    	}
    	for(int i=bl;i<=br;i++) addtag[i]*=c,addtag[i]%=mod,multag[i]*=c,multag[i]%=mod;
    }
    #undef int
    int main(){
    #define int long long
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
    	for(int i=1;i<=belong[n];i++) multag[i]=1;
    	int t=n;
    	while(t--){
    		int w,b,c,d;
    		w=read(),b=read(),c=read(),d=read();
    		if(w==0) add_change(b,c,d);
    		else if(w==1) mul_change(b,c,d);
    		else printf("%lld
    ",query(c)%mod);
    	}
    	return 0;
    }
    

    8 分块8

    区间查询等于c的元素个数,并将区间内的元素改为c

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn=5e5+10;
    const int mod=1e4+7;
    int sum[maxn];
    #define int long long
    int read(){
    	int a=0,op=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
    	return a*op;
    }
    int tag[maxn],a[maxn],belong[maxn];
    int n,m,B;
    void reset(int x){
    	if(tag[x]==-1) return ;
    	for(int i=(x-1)*B+1;i<=x*B;i++) a[i]=tag[x];
    	tag[x]=-1;
    }
    int solve(int l,int r,int c){
    	int ans=0,bl=belong[l]+1,br=belong[r]-1;
    	reset(belong[l]);
    	for(int i=l;i<=min(r,B*belong[l]);i++){
    		if(a[i]!=c) a[i]=c;
    		else ans++;
    	}
    	if(belong[l]!=belong[r]){
    		reset(belong[r]);
    		for(int i=r;i>=(belong[r]-1)*B+1;i--){
    			if(a[i]!=c) a[i]=c;
    			else ans++;
    		}
    	}
    	for(int i=bl;i<=br;i++){
    		if(tag[i]!=-1){
    			if(tag[i]!=c) tag[i]=c;
    			else ans+=B;
    		}
    		else{
    			for(int j=(i-1)*B+1;j<=i*B;j++){
    				if(a[j]!=c) a[j]=c;
    				else ans++;
    			}
    			tag[i]=c;
    		}
    	}
    	return ans;
    }
    #undef int
    int main(){
    #define int long long
    	memset(tag,-1,sizeof(tag));
    	n=read();
    	B=sqrt(n);
    	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
    	int t=n;
    	while(t--){
    		int w,b,c,d;
    		b=read(),c=read(),d=read();
    		printf("%lld
    ",solve(b,c,d));
    	}
    	return 0;
    }
    
  • 相关阅读:
    java基础多线程
    java反射基础
    JSP-4(Session)
    JSP-3
    JSP-2
    复试计算机专业文献翻译
    jsp
    实现输入输出对应模型
    servlet
    tomcat的入门(1)
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/20201110day2-001.html
Copyright © 2011-2022 走看看