CF228D Zigzag 树状数组解法
我们先来考虑若没有特殊数列的性质 , 将其直接转化成一个普通数列 S S S ,此时我们的暴力做法是 O ( N 2 ) O(N^2) O(N2)的 , 若使用二维树状数组 , 对于 ∀ i ∈ [ 1 , n ] \forall i \in [1 , n] ∀i∈[1,n] 都开一个 [ i , n ] [i , n] [i,n]的树状数组的时间复杂度是 O ( l o g n N 2 ) O(log_n N^2) O(lognN2)的。显然对于每一做法我们都是不能接受的 , 所以我们必须对这个特殊的数列下手 , 观察一下发现 , 这是一个以 2 ( z − 1 ) 2(z - 1) 2(z−1)为周期的数列 , 而且 Z Z Z非常的小,给了我们很多优化的空间 , 考虑对解法二进行优化 , 这时因为数列的周期性 , 对于第一个数出现的所有余数开成第二维即可。
对于操作1:暴力修改即可
操作2:对于第一位为Z , 第二维为此时(QL的余数为1时)第一个数的余数 , 再区间求和即可。
考虑到我的描述非常烂 ,便扔一个代码。
#include <bits/stdc++.h>
// WIN
// 加油子
using namespace std ;
typedef long long LL ;
typedef unsigned u64 ;
typedef unsigned uint ;
typedef pair<int , int> PII ;
#define rep(i , a , b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i , a , b) for (int i = (a) ; i >= (b) ; -- i)
const int P = 1e9 + 7 , mo1 = 1234567891 , mo2 = 1e9 + 123 ;
const int N = 1e3 + 12 , Base = 131 , M = 2e3 + 13 ;
template <class Tv>
Tv umin (Tv a , Tv b) {return a < b ? a : b ;}
template <class Tv>
Tv umax (Tv a , Tv b) {return a > b ? a : b ;}
int n , m , s[7][90] ;
int a[100005] ;
struct BIT {
LL C[100005] ;
LL& operator [] (int alp) {return C[alp] ;}
int lowbit (int x) {return x & (-x) ;}
void modify (int x , LL k) {
for (int i = x ; i <= n ; i += lowbit(i)) C[i] += k ;
}
void pri () {
for (int i = 1 ; i <= n ; i ++) {
cout << i << ':' << C[i] << endl ;
}
}
LL query (int x) {
LL res = 0 ;
for (int i = x ; i ; i -= lowbit(i)) {
res += C[i] ;
}
return res ;
}
}bit[7][13] ;
int omi (int v , int z) {
int alp = v % (2 * z - 2) ;
if (!alp) return s[z][v] = 2 , 2 ;
else if (alp > z) return s[z][v] = 2 * z - alp , s[z][v] ;
else return s[z][v] = alp , alp ;
}
int pos (int i , int a , int b) {
if (i == 1) return a ;
int tmp = i % b ;
tmp = !tmp ? b : tmp ;
if (a >= tmp) return a - tmp + 1 ;
else return b + 1 - (tmp - a) ;
}
void change (int ip , int val) {
for (int j = 2 ; j <= 6 ; j ++)
for (int k = 1 ; k <= 2 * (j - 1) ; k ++)
bit[j][pos(ip , k , 2 * j - 2)].modify (ip , 1ll * (val - a[ip]) * s[j][k]) ;
a[ip] = val ;
}
int main () {
scanf ("%d" , &n) ;
for (int j = 2 ; j <= 6 ; j ++) {
for (int k = 1 ; k <= 2 * (j - 1) ; k ++) omi (k , j) ;
}
for (int i = 1 ; i <= n ; i ++) {
scanf ("%d" , & a[i]) ;
for (int j = 2 ; j <= 6 ; j ++) {
for (int k = 1 ; k <= 2 * (j - 1) ; k ++) {
bit[j][pos(i , k , 2 * j - 2)].modify (i , 1ll * a[i] * s[j][k]) ;
}
}
}
scanf ("%d" , &m) ;
while (m--) {
int opt ;
scanf ("%d" , &opt) ;
if (opt == 1) {
int ip , v ;
scanf ("%d%d" , &ip , &v) ;
change (ip , v) ;
}
else {
int ql , qr , z ;
scanf ("%d%d%d" , &ql , &qr , &z) ;
int ip = pos (ql , 1 , (z - 1) * 2) ;
LL res = bit[z][ip].query (qr) - bit[z][ip].query(ql - 1) ;
printf ("%lld\n" , res) ;
}
}
return 0 ;
}