zoukankan      html  css  js  c++  java
  • Loj #6284. 数列分块入门 8

    Description

    Loj传送门

    Solution

    个人认为是 (Loj) 上这几道分块题中比较好的一道题。

    对于这道题,我们对于每一块打一个 (lazy) 标记,表示当前块是否被完整赋过值,即全部赋值为 (c)

    修改时,整块的直接修改 (lazy) 标记,两头多余的部分暴力修改原数组。

    注意: 整个块都要重新赋值一遍。

    • 在查询范围内的:赋值为 (c)

    • 在查询范围外的:赋值为 (lazy) 标记。

    然后把该块的 (lazy) 标记赋值为 (INF)

    查询时,整块的直接判断求和,并把 (lazy) 改为 (c);两头的暴力枚举判断,同时在有 (lazy) 标记时进行上述修改。

    修改的部分我对着数据调了好久 (QwQ)

    经验:一定要想好了在写,不然会漏掉许多细节。

    具体见代码吧。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <map>
    #include <cmath>
    #define INF 1e18
    #define ll long long
    #define ri register int
    
    using namespace std;
    
    inline ll read(){
    	ll x = 0, f = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    	return x * f;
    }
    
    const ll N = 1e5 + 10;
    ll n, B, tot;
    ll a[N], be[N], ml[N], mr[N], lazy[N];
    
    inline void build(){
    	B = sqrt(n);
    	tot = n / B + (B * B != n);
    	for(ri i = 1; i <= n; i++)
    		be[i] = (i - 1) / B + 1;
    	for(ri i = 1; i <= tot; i++){
    		lazy[i] = INF;
    		ml[i] = (i - 1) * B + 1;
    		mr[i] = i * B;
    	}
    	mr[tot] = n;
    }
    
    inline ll calc(int l, int r, int c){
    	ll res = 0;
    	if(lazy[be[l]] == INF){
    		for(ri i = l; i <= r; i++)
    			res += (a[i] == c), a[i] = c;
    	}else{
    		if(lazy[be[l]] == c) res += (r - l + 1);
    		else{
    			for(int i = l; i <= r; i++) a[i] = c;
    			for(int i = ml[be[l]]; i < l; i++) a[i] = lazy[be[l]];
    			for(int i = r + 1; i <= mr[be[l]]; i++) a[i] = lazy[be[l]];
    			lazy[be[l]] = INF;
    		}
    	}
    	return res;
    }
    
    inline ll solve(ll l, ll r, ll c){
    	if(be[l] == be[r]) return calc(l, r, c);
    	ll res = 0;
    	for(ll i = be[l] + 1; i <= be[r] - 1; i++){
    		if(lazy[i] == INF){
    			for(ri j = ml[i]; j <= mr[i]; j++)
    				res += (a[j] == c);
    		}else if(lazy[i] == c) res += B;
    		lazy[i] = c;
    	}
    	res += calc(l, mr[be[l]], c) + calc(ml[be[r]], r, c);
    	return res;
    }
    
    signed main(){
    	freopen("#6284.in", "r", stdin);
    	freopen("#6284.out", "w", stdout);
    	n = read();
    	for(ri i = 1; i <= n; i++)
    		a[i] = read();
    	build();
    	for(ri i = 1; i <= n; i++){
    		ri l = read(), r = read(), c = read();
    		printf("%lld
    ", solve(l, r, c));
    	}
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15388008.html

  • 相关阅读:
    一款你不容错过的Laravel后台管理扩展包 —— Voyager
    关于后台动态模板添加内容的总结 Builder使用
    Python 解决 :NameError: name 'reload' is not defined 问题
    thinkcmf,thinksns,thinkphp,onethink三者是什么关系?
    PHP中用下划线开头的变量含义
    NetBeans 时事通讯(刊号 # 77 Oct 21, 2009)
    NetBeans 时事通讯(刊号 # 78 Oct 27, 2009)
    最受欢迎的中国 50 技术博客评选结果
    祝父亲生日快乐
    最受欢迎的中国 50 技术博客评选结果
  • 原文地址:https://www.cnblogs.com/xixike/p/15388008.html
Copyright © 2011-2022 走看看