[暴力]分块

优化暴力算法

分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\n", ask(x, y));
  		}
  		else
  		{
  			scanf("%d%d%d", &x, &y, &z);
  			change(x, y, z);
  		}
  	}
  	
    return 0;
}

 

posted @ 2019-05-21 12:19  张浦  阅读(99)  评论(0编辑  收藏  举报