zoukankan      html  css  js  c++  java
  • [题解] [笔记] 洛谷-P2357守墓人 & 分块学习笔记

    [题解] [笔记] 洛谷-P2357守墓人 & 分块学习笔记

    原题链

    巨佬儿子的博客

    分块算法

    ​ 分块算法其实是一种暴力算法,主要用于处理序列问题,一般而言是将原序列(长度为你])划分为大小n的块,但存在序列不能完全被刚好分完的情况,因此在序列的末尾可能存在大小不足n的散块.对于两边的散块,每次操作时暴力修改或查询,如果询问或操作区间包含了完整的块,则选择打标记,在询问时再下传标记.

    一些规定

    ​ block[i]代表第i个元素属于第block[i]个块,size代表每个块的大小(不包括散块大小)

    对于此题

    ​ 题目对于主墓地有特殊要求,因此我们每次也特殊处理,在修改操作时,第一次循环for(int i = l;i <= min(block[l] * size,r);i++)从左端点l开始,如果l,r在同一个块内则r < block[l] * size,block[l] * size代表l属于的块的右端点坐标,这个的证明可以从求block[i]的代码反推(block[i] = (i - 1) / size + 1).其余的就是一些细节了.然后就没了.

    AC代码

    #include <bits/stdc++.h>
    using namespace std;
    long long block[200010],tag[200010];
    long long sum[200010],a[200010];
    int main(){
    	int n,f,size;
    	scanf("%d%d",&n,&f);
    	size = sqrt(n);
    	for(int i = 1;i <= n;i++){
    		scanf("%lld",&a[i]);
    		block[i] = (i - 1) / size + 1;
    		sum[block[i]] += a[i];
    	}
    	for(int tt = 1;tt <= f;tt++){
    		int opt;
    		scanf("%d",&opt);
    		if(opt == 1){
    			long long l,r,k;
    			scanf("%lld%lld%lld",&l,&r,&k);
    			for(int i = l;i <= min(r,block[l] * size);i++){
    				a[i] += k;
    				sum[block[i]] += k;
    			}
    			if(block[l] != block[r]){
    				for(int i = r;i >= (block[r] - 1) * size + 1;i--){
    					a[i] += k;
    					sum[block[i]]  += k;
    				}
    			}
    			for(int i = block[l] + 1;i <= block[r] - 1;i++){
    				tag[i] += k;
    			}
    		}
    		else if(opt == 2){
    			int k;
    			scanf("%d",&k);
    			a[1] += k;
    			sum[block[1]] += k;
    		}
    		else if(opt == 3){
    			int k;
    			scanf("%d",&k);
    			a[1] -= k;
    			sum[block[1]] -= k;
    		}
    		else if(opt == 4){
    			long long l,r;
    			long long ans = 0;
    			scanf("%lld%lld",&l,&r);
    			for(int i = l;i <= min(r,block[l] * size);i++){
    				ans += a[i] + tag[block[i]];
    			}
    			if(block[l] != block[r]){
    				for(int  i = r;i >= (block[r] - 1) * size + 1;i--){
    					ans += a[i] + tag[block[i]];
    				}
    			}
    			for(int i = block[l] + 1;i <= block[r] - 1;i++){
    				ans += sum[i] + tag[i] * size;
    			}
    			printf("%lld
    ",ans);
    		}
    		else if(opt == 5){
    			printf("%lld
    ",a[1] + tag[1]);
    		}
    	}
    	return 0;
    }
    

    P.s.:

    好博客

    LOJ上有分块练习1~9

  • 相关阅读:
    grid与oracle用户下oracle程序权限不一致导致无法连接ASM问题
    错误ORA-29760: instance_number parameter not specified的解决办法
    window phone webclient xml 乱码解决方法
    谈谈layout-weight
    状态栏更改颜色
    android 顶部导航栏
    android 布局抽取优化
    Kotlin版HelloWorld
    浅谈synchronized作用
    android获取Tomcat的JSON数据
  • 原文地址:https://www.cnblogs.com/czy--blog/p/13549631.html
Copyright © 2011-2022 走看看