分块初学

以前都以为分块是多么多么牛逼的算法, 没想到竟然是流氓式的暴力

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10 ;
typedef long long ll ;
ll a[N] , pos[N] , R[N] , L[N] , add[N] , sum[N] ;
int n , m , t ;
void change(int l , int r , ll  d)
{
	int p = pos[l] , q = pos[r] ;
	if(q == p)
	 {
	 	for(int i = l ;i <= r ; i ++)
	 	 a[i] += d ;
	 	sum[p] += d * (r - l + 1 ) ;
	 }
	 else 
	  {
	  	for(int i = p + 1 ;i < q ;i ++) add[i] +=d ;
	  	for(int i = l;i <= R[p] ;i ++)
	  	 a[i] +=d ;
	  	sum[p] += d * (R[p] - l + 1) ;
	  	for(int i = L[q] ;i <= r ;i ++)
	  	 a[i] +=d ;
	  	sum[q] += d * (r - L[q] + 1) ; 
	  }
}
ll ask(int l , int r)
{
	int  p = pos[l] , q = pos[r] ;
	ll ans = 0 ;
	if(p == q) 
	{
		for(int i = l;i <= r ;i ++)
		 ans += a[i] ;
		ans += add[p] * (r - l + 1) ;
		
	}
	else 
	 {
	 	for(int i = p + 1 ;i < q ;i ++)
	 	 ans += sum[i] + add[i] * (R[i] - L[i] + 1) ;
	 	for(int i = l ;i <= R[p] ;i ++)
	 	 ans += a[i] ;
	 	ans += add[p] * (R[p] - l + 1) ;
	 	for(int i = L[q] ;i <= r;i ++)
	 	 ans += a[i] ;
	 	ans += add[q] * (r - L[q] + 1) ;
	 }
	 return ans ;
}
int main()
{
	cin >> n >> m ;
	for(int i = 1 ;i <= n ;i ++)
	 scanf("%lld" , &a[i]) ;
	t = sqrt(n) ;
	for(int i = 1 ;i <= n ;i ++)
	 L[i] = (i - 1) * t + 1 , R[i] = i * t ;

	if(R[t] < n) t ++ ,L[t] = R[t - 1] + 1 , R[t] = n ;	
	for(int i = 1; i <= t ;i ++)
	 for(int j = L[i] ;j <= R[i] ;j ++)
	  pos[j] = i , sum[i] += a[j];
	while(m --)
	{
		char str[4] ;
		int l , r , d ;
		scanf("%s%d%d" , &str , &l , &r) ;
		if(str[0] == 'C')
		 {
		 	scanf("%d" , &d) ;
		 	change(l , r , d) ;
		 }
		 else 
		   printf("%lld\n" , ask(l , r)) ;
	}
	return 0 ;
}
posted @ 2019-10-24 18:04  spnooyseed  阅读(91)  评论(0编辑  收藏  举报