分块初学
以前都以为分块是多么多么牛逼的算法, 没想到竟然是流氓式的暴力
#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 ;
}
每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。