CF 228D Zigzag

题目链接:http://codeforces.com/problemset/problem/228/D


题目大意:

要求对a[]单点更新和询问和.


和的形式:


s的定义:



CF 228D Zigzag_第1张图片

题目思路:

小小抱怨一下,这题到比赛结束时居然才10几人搞出来,真坑爹= =...

很明显线段树直接上,入手处2<=z<=6,结点上保存z=2~6的各个和.

从s的定义知道,1<=s<=z,z最大是6,而且我们还发现,s是一个循环的数列:1,2,3,...,z,z-1,z-2,...,1,所以向上更新即为

sum[rt][z][i]=sum[ls][z][i]+sum[rs][z][(i+左子的长度)%cf[z]],cf[z]表示循环节长度.


代码:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

//#define ll __int64
#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle l+r>>1
#define esp (1e-8)
#define type int
#define clr(x,c) memset(x,c,sizeof(x))
#define MOD 1000000007
typedef pair<int,int> pii;

void swap(int &x,int &y){int t=x;x=y;y=t;}
type max(type x,type y){return x>y? x:y;}
type min(type x,type y){return x<y? x:y;}
const int inf=0x3F3F3F3F;
//const double pi=acos(-1.0);
const int M=100000 +5;
int T,cas;

int n,m;
ll a,sum[M<<2][5][11],s[5][M];
ll cf[5]={2,4,6,8,10};

void preSof(){
    for(ll z=2;z<=6;z++){
        ll md=(z-1)<<1;
        for(ll i=1;i<M;i++){
            ll j=i%md;
            if(!j) s[z-2][i-1]=2;
            else if(j<=z) s[z-2][i-1]=j;
            else s[z-2][i-1]=(z<<1)-j;
        }
    }
    return;
}

void pushUp(int llen,int rt){
    for(ll z=2;z<=6;z++)
        for(ll i=0;i<cf[z-2];i++)
            sum[rt][z-2][i]=sum[ls][z-2][i]+sum[rs][z-2][(i+llen)%cf[z-2]];
}

void build(int l,int r,int rt){
    if(l==r){
        scanf("%I64d",&a);
        for(ll z=2;z<=6;z++)
            for(ll i=0;i<cf[z-2];i++)
                sum[rt][z-2][i]=a*s[z-2][i];
        return;
    }
    int mid=middle;
    build(lson),build(rson);
    pushUp(mid-l+1,rt);
}

void update(int l,int r,int rt,int p,ll c){
    if(l==r){
        for(ll z=2;z<=6;z++)
            for(ll i=0;i<cf[z-2];i++)
                sum[rt][z-2][i]=c*s[z-2][i];
        return;
    }
    int mid=middle;
    if(p<=mid) update(lson,p,c);
    else update(rson,p,c);
    pushUp(mid-l+1,rt);
}

ll query(int l,int r,int rt,int L,int R,int z,int i){
    if(L==l && r==R){
        return sum[rt][z][i];
    }
    int mid=middle;
    if(R<=mid) return query(lson,L,R,z,i);
    if(mid<L) return query(rson,L,R,z,i);
    return query(lson,L,mid,z,i)+query(rson,mid+1,R,z,(i+mid-L+1)%cf[z]);
}

void run(){
    int i,j,t,p,v,l,r,z;
    build(1,n,1);
    scanf("%d",&m);
    while(m--){
        scanf("%d",&t);
        if(t==1){
            scanf("%d%d",&p,&v);
            update(1,n,1,p,ll(v));
        }else{
            scanf("%d%d%d",&l,&r,&z);
            printf("%I64d\n",query(1,n,1,l,r,z-2,0));
        }
    }
}

int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    preSof();
    //run();
    while(~scanf("%d",&n)) run();
    //for(scanf("%d",&T),cas=1;cas<=T;cas++) run();
    return 0;
}


你可能感兴趣的:(c,query,Build)