zoukankan      html  css  js  c++  java
  • 数列分块入门1~9 loj6277~6285

    hzwer的讲解

    给出一个长为 (n) 的数列,以及 (n) 个操作,操作涉及区间加法,单点查值。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n, a[50005], opt, uu, vv, ww, tag[305], blc, bel[50005];
    void add(int uu, int vv, int ww){
    	int p=bel[uu], q=bel[vv];
    	if(p==q)
    		for(int i=uu; i<=vv; i++)
    			a[i] += ww;
    	else{
    		for(int i=p+1; i<=q-1; i++)	tag[i] += ww;
    		for(int i=uu; i<=bel[uu]*blc; i++)	a[i] += ww;
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)	a[i] += ww;
    	}
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n);
    	for(int i=1; i<=n; i++)	scanf("%d", &a[i]);
    	for(int i=1; i<=n; i++)	bel[i] = (i - 1) / blc + 1;
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d %d", &opt, &uu, &vv, &ww);
    		if(!opt)	add(uu, vv, ww);
    		else	printf("%d
    ", a[vv]+tag[bel[vv]]);
    	}
    	return 0;
    }
    

    给出一个长为 (n) 的数列,以及 (n) 个操作,操作涉及区间加法,询问区间内小于某个值 (x) 的元素个数。

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    using namespace std;
    int n, blc, a[50005], tag[50005], bel[50005], opt, uu, vv, ww;
    vector<int> vec[50005];
    void qwq(int tat){
    	vec[tat].clear();
    	for(int i=(tat-1)*blc+1; i<=min(tat*blc, n); i++)	vec[tat].push_back(a[i]);
    	sort(vec[tat].begin(), vec[tat].end());
    }
    void update(int uu, int vv, int ww){
    	if(bel[uu]==bel[vv]){
    		for(int i=uu; i<=vv; i++)	a[i] += ww;
    		qwq(bel[uu]);
    	}
    	else{
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++)	tag[i] += ww;
    		for(int i=uu; i<=bel[uu]*blc; i++)	a[i] += ww;
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)	a[i] += ww;
    		qwq(bel[uu]); qwq(bel[vv]);
    	}
    }
    int query(int uu, int vv, int ww){
    	int re=0;
    	if(bel[uu]==bel[vv]){
    		for(int i=uu; i<=vv; i++)
    			if(a[i]+tag[bel[i]]<ww)
    				re++;
    	}
    	else{
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++)
    			re += lower_bound(vec[i].begin(), vec[i].end(), ww-tag[i]) - vec[i].begin();
    		for(int i=uu; i<=bel[uu]*blc; i++)
    			if(a[i]+tag[bel[i]]<ww)
    				re++;
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)
    			if(a[i]+tag[bel[i]]<ww)
    				re++;
    	}
    	return re;
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n/200);
    	for(int i=1; i<=n; i++){
    		bel[i] = (i - 1) / blc + 1;
    		scanf("%d", &a[i]);
    		vec[bel[i]].push_back(a[i]);
    	}
    	for(int i=1; i<=n; i=bel[i]*blc+1)
    		sort(vec[bel[i]].begin(), vec[bel[i]].end());
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d %d", &opt, &uu, &vv, &ww);
    		if(!opt)	update(uu, vv, ww);
    		else	printf("%d
    ", query(uu, vv, ww*ww));
    	}
    	return 0;
    }
    

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的前驱(比其小的最大元素)。

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    using namespace std;
    int n, blc, a[100005], bel[100005], tag[100005], opt, uu, vv, ww;
    vector<int> vec[100005];
    void qwq(int u){
    	vec[u].clear();
    	for(int i=(u-1)*blc+1; i<=min(n, blc*u); i++)
    		vec[u].push_back(a[i]);
    	sort(vec[u].begin(), vec[u].end());
    }
    void update(int uu, int vv, int ww){
    	if(bel[uu]==bel[vv]){
    		for(int i=uu; i<=vv; i++)
    			a[i] += ww;
    		qwq(bel[uu]);
    	}
    	else{
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++)	tag[i] += ww;
    		for(int i=uu; i<=bel[uu]*blc; i++)	a[i] += ww;
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)	a[i] += ww;
    		qwq(bel[uu]); qwq(bel[vv]);
    	}
    }
    int query(int uu, int vv, int ww){
    	int re=0xffffffff;
    	if(bel[uu]==bel[vv]){
    		for(int i=uu; i<=vv; i++)
    			if(a[i]+tag[bel[i]]<ww)
    				re = max(re, a[i]+tag[bel[i]]);
    	}
    	else{
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++){
    			int pos=lower_bound(vec[i].begin(), vec[i].end(), ww-tag[i])-vec[i].begin();
    			if(pos)	re = max(re, vec[i][pos-1]+tag[i]);
    		}
    		for(int i=uu; i<=bel[uu]*blc; i++)
    			if(a[i]+tag[bel[i]]<ww)
    				re = max(re, a[i]+tag[bel[i]]);
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)
    			if(a[i]+tag[bel[i]]<ww)
    				re = max(re, a[i]+tag[bel[i]]);
    	}
    	if(re==0xffffffff)	return -1;
    	else	return re;
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n*log(n)/log(2));
    	for(int i=1; i<=n; i++){
    		scanf("%d", &a[i]);
    		bel[i] = (i - 1) / blc + 1;
    		vec[bel[i]].push_back(a[i]);
    	}
    	for(int i=1; i<=n; i=bel[i]*blc+1)
    		sort(vec[bel[i]].begin(), vec[bel[i]].end());
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d %d", &opt, &uu, &vv, &ww);
    		if(!opt)	update(uu, vv, ww);
    		else	printf("%d
    ", query(uu, vv, ww));
    	}
    	return 0;
    }
    

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,区间求和。

    poj3468

    给出一个长为n的数列,以及n个操作,操作涉及区间开方,区间求和。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n, blc, bel[50005], opt, uu, vv, ww, tag[50005], sum[50005], a[50005];
    int qwq(int uu, int vv){
    	for(int i=uu; i<=vv; i++){
    		sum[bel[i]] -= a[i];
    		a[i] = sqrt(a[i]);
    		sum[bel[i]] += a[i];
    	}
    	return sum[bel[uu]];
    }
    void qaq(int u){
    	if(tag[u])	return ;
    	int re=qwq((u-1)*blc+1, u*blc);
    	if(re>blc)	tag[u] = false;
    	else	tag[u] = true;
    }
    void update(int uu, int vv){
    	if(bel[uu]==bel[vv])
    		qwq(uu, vv);
    	else{
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++)	qaq(i);
    		qwq(uu, bel[uu]*blc);
    		qwq((bel[vv]-1)*blc+1, vv);
    	}
    }
    int query(int uu, int vv){
    	int re=0;
    	if(bel[uu]==bel[vv])
    		for(int i=uu; i<=vv; i++)
    			re += a[i];
    	else{
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++)	re += sum[i];
    		for(int i=uu; i<=bel[uu]*blc; i++)	re += a[i];
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)	re += a[i];
    	}
    	return re;
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n);
    	for(int i=1; i<=n; i++){
    		scanf("%d", &a[i]);
    		bel[i] = (i - 1) / blc + 1;
    		sum[bel[i]] += a[i];
    	}
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d %d", &opt, &uu, &vv, &ww);
    		if(!opt)	update(uu, vv);
    		else	printf("%d
    ", query(uu, vv));
    	}
    	return 0;
    }
    

    给出一个长为n的数列,以及n个操作,操作涉及单点插入,单点询问,数据随机生成。

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    using namespace std;
    typedef pair<int,int> par;
    int n, blc, opt, uu, vv, ww, sta[200005], din, m;
    vector<int> vec[200005];
    par query(int uu){
    	int x=1;
    	while(uu>vec[x].size()){
    		uu -= vec[x].size();
    		x++;
    	}
    	return make_pair(x, uu-1);
    }
    void rebuild(){
    	din = 0;
    	for(int i=1; i<=m; i++){
    		for(int j=0; j<vec[i].size(); j++)
    			sta[++din] = vec[i][j];
    		vec[i].clear();
    	}
    	blc = sqrt(din);
    	for(int i=1; i<=din; i++)
    		vec[(i-1)/blc+1].push_back(sta[i]);
    }
    void update(int uu, int vv){
    	par re=query(uu);
    	vec[re.first].insert(vec[re.first].begin()+re.second, vv);
    	if(vec[re.first].size()>blc+blc)	rebuild();
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n);
    	m = (n - 1) / blc + 1;
    	for(int i=1; i<=n; i++){
    		scanf("%d", &uu);
    		vec[(i-1)/blc+1].push_back(uu);
    	}
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d %d", &opt, &uu, &vv, &ww);
    		if(!opt)	update(uu, vv);
    		else{
    			par re=query(vv);
    			printf("%d
    ", vec[re.first][re.second]);
    		}
    	}
    	return 0;
    }
    

    给出一个长为n的数列,以及n个操作,操作涉及区间乘法,区间加法,单点询问。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n, a[100005], bel[100005], add[100005], mul[100005], blc;
    int opt, uu, vv, ww;
    const int mod=10007;
    void pushDown(int x){
    	for(int i=(x-1)*blc+1; i<=min(n, x*blc); i++)
    		a[i] = (a[i] * mul[x] + add[x]) % mod;
    	mul[x] = 1; add[x] = 0;
    }
    void updAdd(int uu, int vv, int ww){
    	pushDown(bel[uu]);
    	if(bel[uu]==bel[vv])
    		for(int i=uu; i<=vv; i++)
    			a[i] = (a[i] + ww) % mod;
    	else{
    		pushDown(bel[vv]);
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++)	add[i] = (add[i] + ww) % mod;
    		for(int i=uu; i<=bel[uu]*blc; i++)	a[i] = (a[i] + ww) % mod;
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)	a[i] = (a[i] + ww) % mod;
    	}	
    }
    void updMul(int uu, int vv, int ww){
    	pushDown(bel[uu]);
    	if(bel[uu]==bel[vv])
    		for(int i=uu; i<=vv; i++)
    			a[i] = (a[i] * ww) % mod;
    	else{
    		pushDown(bel[vv]);
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++){
    			mul[i] = (mul[i] * ww) % mod;
    			add[i] = (add[i] * ww) % mod;
    		}
    		for(int i=uu; i<=bel[uu]*blc; i++)	a[i] = (a[i] * ww) % mod;
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++)	a[i] = (a[i] * ww) % mod;
    	}	
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n);
    	for(int i=1; i<=n; i++){
    		mul[i] = 1;
    		scanf("%d", &a[i]);
    		bel[i] = (i - 1) / blc + 1;
    	}
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d %d", &opt, &uu, &vv, &ww);
    		if(!opt)	updAdd(uu, vv, ww);
    		else if(opt==1)	updMul(uu, vv, ww);
    		else	printf("%d
    ", (a[vv]*mul[bel[vv]]+add[bel[vv]])%mod);
    	}
    	return 0;
    }
    

    给出一个长为n的数列,以及n个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int n, a[100005], tag[100005], bel[100005], blc, uu, vv, ww;
    void pushDown(int x){
    	if(tag[x]==-1)	return ;
    	for(int i=(x-1)*blc+1; i<=min(n, x*blc); i++)
    		a[i] = tag[x];
    	tag[x] = -1;
    }
    int update(int uu, int vv, int ww){
    	int re=0;
    	if(tag[uu])	pushDown(bel[uu]);
    	if(bel[uu]==bel[vv])
    		for(int i=uu; i<=vv; i++){
    			if(a[i]==ww)
    				re++;
    			a[i] = ww;
    		}
    	else{
    		if(tag[vv])	pushDown(bel[vv]);
    		for(int i=bel[uu]+1; i<=bel[vv]-1; i++){
    			if(tag[i]!=-1)
    				re += tag[i]==ww?blc:0;
    			else
    				for(int j=(i-1)*blc+1; j<=i*blc; j++)
    					re += a[j]==ww;
    			tag[i] = ww;
    		}
    		for(int i=uu; i<=bel[uu]*blc; i++){
    			re += a[i]==ww;
    			a[i] = ww;
    		}
    		for(int i=(bel[vv]-1)*blc+1; i<=vv; i++){
    			re += a[i]==ww;
    			a[i] = ww;
    		}
    	}
    	return re;
    }
    int main(){
    	cin>>n;
    	blc = sqrt(n);
    	for(int i=1; i<=n; i++){
    		tag[i] = -1;
    		scanf("%d", &a[i]);
    		bel[i] = (i - 1) / blc + 1;
    	}
    	for(int i=1; i<=n; i++){
    		scanf("%d %d %d", &uu, &vv, &ww);
    		printf("%d
    ", update(uu, vv, ww));
    	}
    	return 0;
    }
    

    区间众数
    参考luogu4168 蒲公英

  • 相关阅读:
    java操作FTP的一些工具方法
    原生态jdbc的应用技术
    shell脚本重启应用
    性能优化,定时批量入库支持类设计
    linux从零搭建Elasticsearch单机版安装02
    linux从零搭建Elasticsearch之JAVA环境01
    JMX端口开放配置
    druid配置logback日志记录慢sql以及应用数据源监控开启
    java实现BS预览功能
    假分页
  • 原文地址:https://www.cnblogs.com/poorpool/p/8463599.html
Copyright © 2011-2022 走看看