CodeForces 228D. Zigzag(线段树暴力)

原创 2015年07月09日 15:30:10

D. Zigzag
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

The court wizard Zigzag wants to become a famous mathematician. For that, he needs his own theorem, like the Cauchy theorem, or his sum, like the Minkowski sum. But most of all he wants to have his sequence, like the Fibonacci sequence, and his function, like the Euler's totient function.

The Zigag's sequence with the zigzag factor z is an infinite sequence Siz (i ≥ 1; z ≥ 2), that is determined as follows:

  • Siz = 2, when ;
  • , when ;
  • , when .

Operation  means taking the remainder from dividing number x by number y. For example, the beginning of sequence Si3(zigzag factor 3) looks as follows: 1, 2, 3, 2, 1, 2, 3, 2, 1.

Let's assume that we are given an array a, consisting of n integers. Let's define element number i (1 ≤ i ≤ n) of the array as ai. The Zigzag function is function , where l, r, z satisfy the inequalities 1 ≤ l ≤ r ≤ nz ≥ 2.

To become better acquainted with the Zigzag sequence and the Zigzag function, the wizard offers you to implement the following operations on the given array a.

  1. The assignment operation. The operation parameters are (p, v). The operation denotes assigning value v to the p-th array element. After the operation is applied, the value of the array element ap equals v.
  2. The Zigzag operation. The operation parameters are (l, r, z). The operation denotes calculating the Zigzag function Z(l, r, z).

Explore the magical powers of zigzags, implement the described operations.

Input

The first line contains integer n (1 ≤ n ≤ 105) — The number of elements in array a. The second line contains n space-separated integers: a1, a2, ..., an (1 ≤ ai ≤ 109) — the elements of the array.

The third line contains integer m (1 ≤ m ≤ 105) — the number of operations. Next m lines contain the operations' descriptions. An operation's description starts with integer ti (1 ≤ ti ≤ 2) — the operation type.

  • If ti = 1 (assignment operation), then on the line follow two space-separated integers: pi, vi (1 ≤ pi ≤ n; 1 ≤ vi ≤ 109) — the parameters of the assigning operation.
  • If ti = 2 (Zigzag operation), then on the line follow three space-separated integers: li, ri, zi (1 ≤ li ≤ ri ≤ n; 2 ≤ zi ≤ 6) — the parameters of the Zigzag operation.

You should execute the operations in the order, in which they are given in the input.

Output

For each Zigzag operation print the calculated value of the Zigzag function on a single line. Print the values for Zigzag functions in the order, in which they are given in the input.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use cincout streams or the %I64dspecifier.

Sample test(s)
input
5
2 3 1 5 5
4
2 2 3 2
2 1 5 3
1 3 5
2 1 5 3
output
5
26
38
Note

Explanation of the sample test:

  • Result of the first operation is Z(2, 3, 2) = 3·1 + 1·2 = 5.
  • Result of the second operation is Z(1, 5, 3) = 2·1 + 3·2 + 1·3 + 5·2 + 5·1 = 26.
  • After the third operation array a is equal to 2, 3, 5, 5, 5.
  • Result of the forth operation is Z(1, 5, 3) = 2·1 + 3·2 + 5·3 + 5·2 + 5·1 = 38.


大致思路:Z从2到6,按循环节分别维护一棵线段树,一共维护30棵线段树,查询复杂度logn的,修改的复杂度是30*logn

时限3s,毕竟codeforces可过


//137924k	1372ms	GNU G++ 4.9.2 2761B
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;

#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N = 1e5+100;
ll sum[35][N<<2];
ll val[N],mul[35][N];
int n;

inline void pushup(int rt,ll *sum)
{
    sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt,ll sum[],ll mul[])
{
    if(l == r)
    {
        sum[rt] = val[l]*mul[l];
        return ;
    }
    int m = (l+r)>>1;
    build(lson,sum,mul);
    build(rson,sum,mul);
    pushup(rt,sum);
}
void update(int pos,ll x,int l,int r,int rt,ll sum[],ll mul[])
{
    if(l == r)
    {
        sum[rt] = x*mul[l];
        return ;
    }
    int m = (l+r)>>1;
    if(pos <= m) update(pos,x,lson,sum,mul);
    else update(pos,x,rson,sum,mul);
    pushup(rt,sum);
}
ll query(int L,int R,int l,int r,int rt,ll sum[])
{
    if(L <= l && r <= R)
    {
        return sum[rt];
    }
    ll ans = 0;
    int m = (l+r)>>1;
    if(L <= m) ans += query(L,R,lson,sum);
    if(R > m) ans += query(L,R,rson,sum);
    return ans;
}

inline int getid(int l,int z)
{
    int buf = 0;
    REP(i,z-2) buf += 2*i;
    int k = 2*(z-1);
    l = (l-1)%k+1;
    if(l == 1) return l+buf;
    return k-l+2+buf;
}

int main()
{
//......................
    ll a[15];
    a[1] = 1,a[2] = 2;
    REP(i,2)REP(j,N-10) mul[i][j] = a[(j-1+i-1)%2+1];
    a[3] = 3,a[4] = 2;
    REP(i,4)REP(j,N-10) mul[2+i][j] = a[(j-1+i-1)%4+1];
    a[4] = 4,a[5] = 3,a[6] = 2;
    REP(i,6)REP(j,N-10) mul[6+i][j] = a[(j-1+i-1)%6+1];
    a[5] = 5,a[6] = 4,a[7] = 3,a[8] = 2;
    REP(i,8)REP(j,N-10) mul[12+i][j] = a[(j-1+i-1)%8+1];
    a[6] = 6,a[7] = 5,a[8] = 4,a[9] = 3,a[10] = 2;
    REP(i,10)REP(j,N-10) mul[20+i][j] = a[(j-1+i-1)%10+1];
//.......................

    cin>>n;
    REP(i,n) scanf("%I64d",&val[i]);
    REP(i,30) build(root,sum[i],mul[i]);
    int Q;
    cin>>Q;
    REP(i,Q)
    {
        int op;
        scanf("%d",&op);
        if(op == 1)
        {
            int pos;ll x;
            scanf("%d%I64d",&pos,&x);
            REP(i,30) update(pos,x,root,sum[i],mul[i]);
        }
        else
        {
            int l,r,z;
            scanf("%d%d%d",&l,&r,&z);
            int id = getid(l,z);
            printf("%I64d\n",query(l,r,root,sum[id]));
        }
    }
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Codeforces Round #365 (Div. 2) A(暴力) B(数学技巧) C(二分)D(线段树+离散)E(乘除法DP+约数分解+map映射)

传送门:A. Mishka and Game 暴力记录两人赢的次数,最后将次数再比较一次即可 #include using namespace std; int n; int main()...

CodeForces - 400E(模拟+线段树或暴力)

CodeForces - 400E(模拟+线段树或暴力)

【线段树+均摊思想】UOJ #228 基础数据结构练习题

题面在这里 首先吐槽一下这个题目的名字【大雾 题目意思很简单,但是需要思考的地方很多 主要问题在于如何实现区间开根号 试想:两个不同的数x,y开若干次根号后,必然会趋向于一致: 330 22...
  • linkfqy
  • linkfqy
  • 2017年05月23日 15:47
  • 1097

[均摊 线段树] UOJ#228. 基础数据结构练习题

题意题解先膜一下九老师 %%% 可以先感性理解一下,不断进行区间开根号操作,整个序列会不断“趋近于一致“。比如说: 3123 42 5 --> 55 6 2 --> 7 2 1 --> 2 1 ...
  • CHHNZ
  • CHHNZ
  • 2017年05月20日 19:43
  • 206

Codeforces 629 D Finals in arithmetic(最大上升子序列和,O(nlogn)、线段树/树状数组)

题目链接: Codeforces 629 D Finals in arithmetic 题意: 已知nn块圆柱形蛋糕的底面圆半径和高,需要利用这些蛋糕尽可能堆成一个体积最大的蛋糕,但是需要满足:...
  • Ramay7
  • Ramay7
  • 2016年07月25日 10:52
  • 262

codeforces 19D 线段树

题意:有三种指令:向平面上增加一个点、减少一个点,或者给定一个点,在以它为原点的第一象限内找到x最小的点。如果有多个,要求y最小。坐标范围0到1e9,至多2e5条指令。 #include #incl...

codeforces round 355 div2 D Vanya and Treasure Dp 二维线段树

#pragma warning(disable:4786) #pragma comment(linker, "/STACK:102400000,102400000") #include #includ...
  • jijijix
  • jijijix
  • 2016年12月16日 22:54
  • 93

【CodeForces】19D Points 线段树+set

传送门:【CodeForces】19D Points 题目分析:

codeforces 629 D. Babaei and Birthday Cake dp + 线段树

题意有n个圆柱形蛋糕,现在需要把他们叠在一起,要求标号小的蛋糕在下面,并且要求保证下面的蛋糕的体积严格的比上面的小。思路类似于“最重子序列”,用dp[i]以第i个蛋糕为最高的能得到的最大的体积。dp[...

codeforces 46D 线段树区间合并

题意: 思路:
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CodeForces 228D. Zigzag(线段树暴力)
举报原因:
原因补充:

(最多只允许输入30个字)