zoukankan      html  css  js  c++  java
  • [暴力]分块

    优化暴力算法

    分sqrt(n)个区间进行维护

    复杂度3 sqrt(n) = sqrt(n)


    代码: 建块

    
    int n, m;
    ll arr[MAXN] = {0}; //原数组
    ll belong[MAXN], bsize = 0; //对应块 块大小
    ll fst[MAXN], lst[MAXN], rmax[MAXN] = {0}; //对应块起始地址 块维护信息
    void build()
    {
        bsize = sqrt(n);
        
        for(int i = 1; i <= bsize; ++i)
            fst[i] = (i - 1) * bsize + 1, lst[i] = i * bsize;
            
        if(lst[bsize] < n)
            ++bsize, fst[bsize] = lst[bsize - 1] + 1, lst[bsize] = n; //维护尾段
            
        for(int i = 1; i <= bsize; ++i)
            for(int j = fst[i]; j <= lst[i]; ++j)
                belong[j] = i;
    }

    查询:

    
    ll ask(int x, int y)
    {
        ll ans = 0;
        
        if(belong[x] == belong[y]) //同一块内暴力查询
        {
           for(int i = x; i <= y; ++i)
                ans = max(ans, arr[i]);
        }
        
        else
        {
            for(int i = x; i <= lst[ belong[x]]; ++i ) //暴力查询区间
                ans = max(ans, arr[i]);
            for(int i = belong[x] + 1; i < belong[y]; ++i) //快速查询块内信息
                ans = max(ans, rmax[i]);
            for(int i = fst[belong[y]]; i <= y; ++i) //暴力查询后区间
                ans = max(ans, arr[i]);
        }
        return ans;
    }

    区间加和区间和模板

    /*
        Zeolim - An AC a day keeps the bug away
    */
     
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    #include<queue>
    using namespace std;
    
    #define mp(x, y) make_pair(x, y)
    #define fr(x, y, z) for(int x = y; x < z; ++x)
    
    typedef long long ll;
    typedef double ld;
    typedef std::pair<int, int> pii;
    typedef std::vector <short> vi;
    //typedef __int128 ill;
    
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 1e18;
    const ll MOD = 1e9 + 7;
    const int MAXN = 1e6 + 100;
    
    int n, m;
    
    ll arr[MAXN] = {0}; //原数组
    
    ll belong[MAXN], bsize = 0; //对应块 块大小
    
    ll fst[MAXN], lst[MAXN], sum[MAXN] = {0}, add[MAXN] = {0}; //对应块起始地址 块维护信息
    
    void build()
    {
        bsize = sqrt(n);
        
        for(int i = 1; i <= bsize; ++i)
            fst[i] = (i - 1) * bsize + 1, lst[i] = i * bsize;
            
        if(lst[bsize] < n)
            ++bsize, fst[bsize] = lst[bsize - 1] + 1, lst[bsize] = n; //维护尾段
            
        for(int i = 1; i <= bsize; ++i)
            for(int j = fst[i]; j <= lst[i]; ++j)
            {
                belong[j] = i;
                sum[i] += arr[j];
            }
    }
    
     
    ll ask(int x, int y)
    {
        ll ans = 0;
        
        if(belong[x] == belong[y]) //同一块内暴力查询
        {
           for(int i = x; i <= y; ++i)
                ans = ans + arr[i] + add[belong[x]];
        }
        
        else
        {
            for(int i = x; i <= lst[ belong[x]]; ++i ) //暴力查询区间
                ans = ans + arr[i] + add[belong[i]];
            for(int i = belong[x] + 1; i < belong[y]; ++i) //快速查询块内信息
                ans += sum[i];
            for(int i = fst[belong[y]]; i <= y; ++i) //暴力查询后区间
                ans = ans + arr[i] + add[belong[i]];
        }
        return ans;
    }
    
    void change(int x, int y, int val)
    {
    	if(belong[x] == belong[y]) //同一块内暴力查询
        {
           for(int i = x; i <= y; ++i)
                arr[i] += val, sum[belong[i]] += val;
        }
        
        else
        {
            for(int i = x; i <= lst[ belong[x]]; ++i ) //暴力查询区间
                arr[i] += val, sum[belong[i]] += val;
            for(int i = belong[x] + 1; i < belong[y]; ++i) //快速查询块内信息
                add[i] += val, sum[i] += (lst[i] - fst[i] + 1) * val;
            for(int i = fst[belong[y]]; i <= y; ++i) //暴力查询后区间
                arr[i] += val, sum[belong[i]] += val;
        }
    }
    
    int main()
    {  
        //ios::sync_with_stdio(0);
        //cin.tie(0); cout.tie(0);
        //freopen("d:out.txt","w",stdout);
      	//freopen("d:in.txt","r",stdin);
      	
      	scanf("%d%d", &n, &m);
    
      	fr(i, 1, n + 1)
      		scanf("%lld", &arr[i]);
    
      	build();
    
      	char op;
    
      	int x, y, z;
    
      	fr(i, 0, m)
      	{
      		scanf(" %c", &op);
    
      		if(op == 'Q')
      		{
      			scanf("%d%d", &x, &y);
      			printf("%lld
    ", ask(x, y));
      		}
      		else
      		{
      			scanf("%d%d%d", &x, &y, &z);
      			change(x, y, z);
      		}
      	}
      	
        return 0;
    }
    
  • 相关阅读:
    装饰器详解
    面试题求 平衡点
    Python面试题
    With语句上下文管理
    多个装饰器修饰一个函数
    NGINX部署配置参考.
    Django ORM操作
    MYsql 之多表查询.
    [数据结构与算法] : 二叉查找树
    [数据结构与算法] : 队列
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270361.html
Copyright © 2011-2022 走看看