• loj数列分块入门


    入门 1-区间加法-单点查询

    在这里插入图片描述

    ll n,a[maxn],lazy[maxn];
    int main() {
    	n = read;
    	for(int i=1; i<=n; i++) a[i] = read;
    	int blk = sqrt(n);
    	for(int ii=1; ii<=n; ii++) {
    		int op = read,l = read,r = read,c = read;
    		if( op == 0) {
    			for(int i=l; i<min(r+1,(l/blk+1)*blk); i++) {
    				a[i] += c;
    			}
    			for(int i=l/blk+1; i<r/blk; i++) {
    				lazy[i] += c;
    			}
    			if(l / blk != r / blk) {
    				for(int i=r/blk*blk; i<=r; i++) a[i] += c;
    			}
    		} else {
    			printf("%lld
    ",a[r] + lazy[r/blk]);
    		}
    	}
    	return 0;
    }
    /**
    4
    1 2 2 3
    0 1 3 1
    1 0 1 0
    0 1 2 2
    1 0 2 0
    
    2
    5
    **/
    

    入门 2-区间加法-区间查询

    在这里插入图片描述

    const int maxn = 1e5 + 7;
    ll n, a[maxn];
    vector<ll> vet[maxn];
    ll blk, lazy[maxn], b[maxn];
    void reget(int id) {
        vet[id].clear();
    
        for (int i = (id - 1) * blk + 1; i <= min(n, id * blk); i++) {
            vet[id].push_back(a[i]);
        }
    
        sort(vet[id].begin(), vet[id].end());
    }
    void update(ll l, ll r, ll c) {
        for (int i = l; i <= min(b[l]*blk, r); i++)
            a[i] += c;
    
        reget(b[l]);
    
        if (b[l] != b[r]) {
            for (int i = (b[r] - 1) * blk + 1; i <= r; i++)
                a[i] += c;
    
            reget(b[r]);
        }
    
        for (int i = b[l] + 1; i <= b[r] - 1; i++) {
            lazy[i] += c;
        }
    }
    ll query(ll l, ll r, ll val) {
        ll ret = 0;
    
        for (int i = l; i <= min(b[l]*blk, r); i++) {
            if (a[i] + lazy[b[l]] < val)
                ++ ret;
        }
    
        if (b[l] != b[r]) {
            for (int i = (b[r] - 1) * blk + 1; i <= r; i++) {
                if (a[i] + lazy[b[r]] < val)
                    ++ ret;
            }
        }
    
        for (int i = b[l] + 1; i <= b[r] - 1; i++) {
            int get = val - lazy[i];
            //      ret += upper_bound(vet[i].begin(),vet[i].end(),get) - lower_bound(vet[i].begin(),vet[i].end(),get);
            ret += lower_bound(vet[i].begin(), vet[i].end(), get) - vet[i].begin();
        }
    
        return ret;
    }
    int main() {
        n = read;
    
        for (int i = 1; i <= n; i++)
            a[i] = read;
    
        blk = sqrt(n);
    
        for (int i = 1; i <= n; i++) {
            b[i] = (i - 1) / blk + 1;
            vet[b[i]].push_back(a[i]);
        }
    
        for (int i = 1; i <= b[n]; i++)
            sort(vet[i].begin(), vet[i].end());
    
        for (int i = 1; i <= n; i++) {
            int op = read, l = read, r = read, c = read;
    
            if (op == 0)
                update(l, r, c);
            else
                printf("%lld
    ", query(l, r, c * c));
        }
    
        return 0;
    }
    /**
    4
    1 2 2 3
    0 1 3 1
    1 1 3 2
    1 1 4 1
    1 2 3 2
    
    3
    0
    2
    **/
    

    入门 3-区间加法-单点查询

    在这里插入图片描述

    const int maxn = 1e5 + 7;
    ll n, a[maxn];
    vector<ll> vet[maxn];
    ll blk, lazy[maxn], b[maxn];
    void reget(int id) {
        vet[id].clear();
    
        for (int i = (id - 1) * blk + 1; i <= min(n, id * blk); i++) {
            vet[id].push_back(a[i]);
        }
    
        sort(vet[id].begin(), vet[id].end());
    }
    void update(ll l, ll r, ll c) {
        for (int i = l; i <= min(b[l]*blk, r); i++)
            a[i] += c;
    
        reget(b[l]);
    
        if (b[l] != b[r]) {
            for (int i = (b[r] - 1) * blk + 1; i <= r; i++)
                a[i] += c;
    
            reget(b[r]);
        }
    
        for (int i = b[l] + 1; i <= b[r] - 1; i++) {
            lazy[i] += c;
        }
    }
    ll query(ll l, ll r, ll val) {
        ll ret = -1;
    
        for (int i = l; i <= min(b[l]*blk, r); i++) {
            if (a[i] + lazy[b[l]] < val)
                ret = max(ret, a[i] + lazy[b[l]]);
        }
    
        if (b[l] != b[r]) {
            for (int i = (b[r] - 1) * blk + 1; i <= r; i++) {
                if (a[i] + lazy[b[r]] < val)
                    ret = max(ret, a[i] + lazy[b[r]]);
            }
        }
    
        for (int i = b[l] + 1; i <= b[r] - 1; i++) {
            ll get = val - lazy[i];
            vector<ll>::iterator l = lower_bound(vet[i].begin(), vet[i].end(), get);
    
            if (l == vet[i].begin())
                continue;
    
            l --;
            ret = max(ret, *l + lazy[i]);
        }
    
        return ret;
    }
    int main() {
        n = read;
    
        for (int i = 1; i <= n; i++)
            a[i] = read;
    
        blk = sqrt(n);
    
        for (int i = 1; i <= n; i++) {
            b[i] = (i - 1) / blk + 1;
            vet[b[i]].push_back(a[i]);
        }
    
        for (int i = 1; i <= b[n]; i++)
            sort(vet[i].begin(), vet[i].end());
    
        for (int i = 1; i <= n; i++) {
            int op = read, l = read, r = read, c = read;
    
            if (op == 0)
                update(l, r, c);
            else
                printf("%lld
    ", query(l, r, c));
    
            //      debug(i);
        }
    
        return 0;
    }
    /**
    4
    1 2 2 3
    0 1 3 1
    1 1 4 4
    0 1 2 2
    1 1 2 4
    
    3
    -1
    **/
    

    入门 4-区间加法-区间查询

    在这里插入图片描述

    ll n,a[maxn];
    ll blk,lazy[maxn],b[maxn],sum[maxn];
    void update(ll l,ll r,ll c) {
    	for(int i=l; i<=min(b[l]*blk,r); i++) a[i] += c,sum[b[l]] += c;
    	if(b[l] != b[r]) {
    		for(int i=(b[r] - 1) * blk+1; i<=r; i++) a[i] += c,sum[b[r]] += c;
    	}
    	for(int i=b[l]+1; i<=b[r] - 1; i++) {
    		lazy[i] += c;
    	}
    }
    ll query(ll l,ll r,ll val) {
    	ll ret = 0;
    	for(int i=l; i<=min(b[l]*blk,r); i++) {
    		ret += a[i] + lazy[b[l]];
    		ret %= (val + 1);
    	}
    	if(b[l] != b[r]) {
    		for(int i=(b[r]-1)*blk+1; i<=r; i++) {
    			ret += a[i] + lazy[b[r]];
    			ret %= (val + 1);
    		}
    	}
    	for(int i=b[l]+1; i<=b[r]-1; i++) {
    		ll add = lazy[i] * blk % (val + 1);
    		ret += (sum[i] + add) % (val + 1);
    		ret %= (val + 1);
    	}
    	return ret;
    }
    int main() {
    	n = read;
    	for(int i=1; i<=n; i++) a[i] = read;
    	blk = sqrt(n);
    	for(int i=1; i<=n; i++) {
    		b[i] = (i - 1) / blk + 1;
    		sum[b[i]] += a[i];
    	}
    	for(int i=1; i<=n; i++) {
    		int op = read,l = read,r = read,c = read;
    		if(op == 0) update(l,r,c);
    		else printf("%lld
    ",query(l,r,c));
    	}
    	return 0;
    }
    /**
    4
    1 2 2 3
    0 1 3 1
    1 1 4 4
    0 1 2 2
    1 1 2 4
    
    1
    4
    **/
    

    入门 5-区间开方-区间查询

    在这里插入图片描述

    ll n,a[maxn];
    ll blk,lazy[maxn],b[maxn],sum[maxn];
    bool vis[maxn];
    bool check(int id) {
    	if(vis[id]) return true;
    	for(int i=(id-1)*blk+1; i<=min(n,blk*id); i++) {
    		if(a[i] > 1) return false;
    	}
    	return vis[id] = 1;
    }
    void update(ll l,ll r) {
    	if(!check(b[l])) {
    		for(int i=l; i<=min(b[l]*blk,r); i++) {
    			sum[b[l]] -= a[i];
    			a[i] = sqrt(a[i]);
    			sum[b[l]] += a[i];
    		}
    	}
    	if(b[l] != b[r] && !check(b[r])) {
    		for(int i=(b[r]-1)*blk+1; i<=r; i++) {
    			sum[b[r]] -= a[i];
    			a[i] = sqrt(a[i]);
    			sum[b[r]] += a[i];
    		}
    	}
    	for(int i=b[l]+1; i<=b[r]-1; i++) {
    		if(!check(i)) {
    			sum[i] = 0;
    			for(int j=(i-1)*blk+1; j<=i*blk; j++) {
    				a[j] = sqrt(a[j]);
    				sum[i] += a[j];
    			}
    		}
    	}
    }
    ll query(ll l,ll r) {
    	ll ret = 0;
    	for(int i=l; i<=min(b[l]*blk,r); i++) {
    		ret += a[i];
    	}
    	if(b[l] != b[r]) {
    		for(int i=(b[r]-1)*blk+1; i<=r; i++) {
    			ret += a[i];
    		}
    	}
    	for(int i=b[l]+1; i<=b[r]-1; i++) {
    		ret += sum[i];
    	}
    	return ret;
    }
    int main() {
    	n = read;
    	for(int i=1; i<=n; i++) a[i] = read;
    	blk = sqrt(n);
    	for(int i=1; i<=n; i++) {
    		b[i] = (i - 1) / blk + 1;
    		sum[b[i]] += a[i];
    	}
    	for(int i=1; i<=n; i++) {
    		int op = read,l = read,r = read,c = read;
    		if(op == 0) update(l,r);
    		else printf("%lld
    ",query(l,r));
    	}
    	return 0;
    }
    /**
    4
    1 2 2 3
    0 1 3 1
    1 1 4 4
    0 1 2 2
    1 1 2 4
    
    6
    2
    **/
    

    入门 6-单点插入-单点查询

    在这里插入图片描述

    typedef pair<int,int> PII;
    ll n,a[maxn];
    ll blk,lazy[maxn],b[maxn],sum[maxn],tot;
    vector<int> vet[maxn];
    void reBuild() {
    	int p = 0;
    	for(int i=1; i<=tot; i++) {
    		for(int val : vet[i]) {
    			a[++p] = val;
    		}
    		vet[i].clear();
    	}
    	blk = sqrt(p);
    	tot = ceil(1.0 * p / blk);
    	for(int i=1; i<=p; i++) {
    		b[i] = (i - 1) / blk + 1;
    		vet[b[i]].push_back(a[i]);
    	}
    }
    PII query(ll r) {
    	for(int i=1; i<=tot; i++) {
    		if(r > vet[i].size()) r -= vet[i].size();
    		else return {i,r-1};
    	}
    }
    void insert(ll l,ll r) {
    	PII t = query(l);
    	vet[t.first].insert(vet[t.first].begin() + t.second,r);
    	if(vet[t.first].size() > 10 * blk) reBuild();
    }
    int main() {
    	n = read;
    	for(int i=1; i<=n; i++) a[i] = read;
    	blk = sqrt(n);
    	tot = ceil(1.0*n / blk);
    	for(int i=1; i<=n; i++) {
    		b[i] = (i - 1) / blk + 1;
    		vet[b[i]].push_back(a[i]);
    	}
    	for(int i=1; i<=n; i++) {
    		int op = read,l = read,r = read,c = read;
    		if(op == 0) insert(l,r);
    		else {
    			PII t = query(r);
    			printf("%d
    ",vet[t.first][t.second]);
    		}
    	}
    	return 0;
    }
    /**
    4
    1 2 2 3
    0 1 3 1
    1 1 4 4
    0 1 2 2
    1 1 2 4
    
    2
    3
    **/
    

    入门 7-区间乘法-区间加法-单点查询

    在这里插入图片描述

    const int maxn = 1e5 + 7;
    const int mod = 10007;
    ll n,a[maxn];
    ll blk,add[maxn],b[maxn],sum[maxn],mul[maxn];
    void pushDown(int id) {
    	for(int i=(id-1) * blk + 1; i<=min(id * blk,n); i++) {
    		a[i] = (a[i] * mul[id] % mod + add[id] + mod) % mod;
    	}
    	mul[id] = 1;
    	add[id] = 0;
    }
    void add_mul(int l,int r,ll val,int op) {
    	pushDown(b[l]);
    	for(int i=l; i<=min(b[l]*blk,1LL*r); i++) {
    		if(op) a[i] = (a[i] * val) % mod;
    		else a[i] = (a[i] + val) % mod;
    	}
    	if(b[l] != b[r]) {
    		pushDown(b[r]);
    		for(int i=(b[r]-1)*blk + 1; i<=r; i++) {
    			if(op) a[i] = (a[i] * val) % mod;
    			else a[i] = (a[i] + val) % mod;
    		}
    	}
    	for(int i=b[l]+1; i<=b[r]-1; i++) {
    		if(op) mul[i] = (mul[i] * val) % mod,add[i] = (add[i] * val) % mod;
    		else add[i] = (add[i] + val) % mod;
    	}
    }
    ll query(int r) {
    	ll ret = 0;
    	ret = (a[r] * mul[b[r]] % mod + add[b[r]]) % mod;
    	return ret;
    }
    int main() {
    	n = read;
    	for(int i=1; i<=n; i++) a[i] = read;
    	blk = sqrt(n);
    	for(int i=1; i<=n; i++) {
    		b[i] = (i - 1) / blk + 1;
    		mul[b[i]] = 1;
    		add[b[i]] = 0;
    	}
    	for(int i=1; i<=n; i++) {
    		int op = read,l = read,r = read,c = read;
    		if(op == 2) {
    			printf("%lld
    ",query(r));
    		} else {
    			add_mul(l,r,c,op);
    		}
    	}
    	return 0;
    }
    /**
    7
    1 2 2 3 9 3 2
    0 1 3 1
    2 1 3 1
    1 1 4 4
    0 1 7 2
    1 2 6 4
    1 1 6 5
    2 2 6 4
    
    3
    100
    **/
    
    

    入门 8-区间修改-区间查询

    在这里插入图片描述

    ll n,a[maxn];
    ll blk,add[maxn],b[maxn],upd[maxn];
    void reset(int id) {
    	if(upd[id] == -1) return ;
    	for(int i=(id-1) * blk+1; i<=min(id*blk,n); i++) {
    		a[i] = upd[id];
    	}
    	upd[id] = -1;
    }
    ll getSet(int l,int r,ll val) {
    	ll ans = 0;
    	reset(b[l]);
    	for(int i=l; i<=min(b[l]*blk,1LL*r); i++) {
    		ans += a[i] == val;
    		a[i] = val;
    	}
    
    	if(b[l] != b[r]) {
    		reset(b[r]);
    		for(int i=(b[r]-1)*blk + 1; i<=r; i++) {
    			ans += a[i] == val;
    			a[i] = val;
    		}
    	}
    	for(int i=b[l]+1; i<=b[r]-1; i++) {
    		if(upd[i] == -1) {
    			for(int j=(i-1)*blk+1; j<=i*blk; j++) {
    				ans += a[j] == val;
    			}
    		} else ans += upd[i] == val?blk:0;
    		upd[i] = val;
    	}
    	return ans;
    }
    int main() {
    	n = read;
    	for(int i=1; i<=n; i++) a[i] = read;
    	blk = sqrt(n);
    	for(int i=1; i<=n; i++) {
    		b[i] = (i - 1) / blk + 1;
    		upd[b[i]] = -1;
    	}
    	for(int i=1; i<=n; i++) {
    		int l = read,r = read,c = read;
    		ll ans = getSet(l,r,c);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    /**
    4
    1 2 2 4
    1 3 1
    1 4 4
    1 2 2
    1 4 2
    
    1
    1
    0
    2
    **/
    

    入门 9-区间查询众数

    在这里插入图片描述

    #define Clear(x,val) memset(x,val,sizeof x)
    ll n,a[maxn],ans[2007][2007],b[maxn],blk,cnt[maxn],num;
    vector<int> vet[maxn];
    map<int,int> vis,val;
    void get(int id) {
    	Clear(cnt,0);
    	int mx = 0,res = 0;
    	for(int i=(id-1) * blk + 1; i<=n; i++) {
    		int to = b[i];///cur is the b[i]-th blk
    		++ cnt[a[i]];/// the amt ++
    		if(cnt[a[i]] > mx || (cnt[a[i]] == mx && val[a[i]] < val[res])) {
    			res = a[i];/// set the cur mx value
    			mx = cnt[a[i]];
    		}
    		ans[id][to] = res;/// from blk id -> blk to  the ans = res
    	}
    }
    int getNum(int l,int r,int x) {
    	int ret = 0;
    	ret = upper_bound(vet[x].begin(),vet[x].end(),r) - lower_bound(vet[x].begin(),vet[x].end(),l);/// amount of x
    	return ret;
    }
    ll query(int l,int r) {
    	ll ret = ans[b[l] + 1][b[r] - 1];// center blks
    	int mx = getNum(l,r,ret);// get the amount of this
    	for(int i=l; i<=min(r*1LL,b[l]*blk); i++) {
    		int amt = getNum(l,r,a[i]);
    		if(amt > mx || (amt == mx && val[a[i]] < val[ret])) { ///val[ret]
    			ret = a[i];
    			mx = amt;
    		}
    	}
    	if(b[l] != b[r]) {
    		for(int i = (b[r] - 1) * blk + 1; i<=r; i++) {
    			int amt = getNum(l,r,a[i]);
    			if(amt > mx || (amt == mx && val[a[i]] < val[ret])) {
    				ret = a[i];
    				mx = amt;
    			}
    		}
    	}
    	return val[ret];
    }
    int main() {
    	n = read;
    	blk = sqrt(n);
    	blk = 80;
    	for(int i=1; i<=n; i++) {
    		a[i] = read;
    		b[i] = (i - 1) / blk + 1;
    		if(!vis[a[i]]) {
    			vis[a[i]] = ++ num;
    			val[num] = a[i];///¶ÔÓ¦ÏÂ
    		}
    		a[i] = vis[a[i]];
    		vet[a[i]].push_back(i);
    	}
    	for(int i=1; i<=b[n]; i++) get(i); /// get the i-th blk
    	for(int i=1; i<=n; i++) {
    		int l = read,r = read;
    		if(l > r) swap(l,r);
    		ll ans = query(l,r);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    /**
    4
    1 2 2 4
    1 2
    1 4
    2 4
    3 4
    
    1
    2
    2
    2
    **/
    

    七夕快乐
    在这里插入图片描述

  • 相关阅读:
    12月12日总结
    练习:请用索引取出下面list的指定元素:
    练习:小明身高1.75,体重80.5kg。请根据BMI公式(体重除以身高的平方)帮小明计算他的BMI指数,并根据BMI指数:
    练习:请利用循环依次对list中的每个名字打印出Hello, xxx!:
    练习:学员管理系统
    练习:请修改列表生成式,通过添加if语句保证列表生成式能正确地执行
    CF1067D Computer Game
    高等数学第三章
    CF755G PolandBall and Many Other Balls
    TS泛型工具
  • 原文地址:https://www.cnblogs.com/PushyTao/p/15459815.html
Copyright © 2020-2023  润新知