HDU 4267 A Simple Problem with Integers

2012长春网络赛1001题
 
比赛时没写出来,一直TLE(标记结构不能拉链表,而要直接开10*10的数组)
思路:把数组分成sqrt(n)块,块内暴力更新 块间更新标记
复杂度 O(55*n*sqrt(n))
 
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;


const int N=50010;
const int SQN=800;

struct Flag{
    int x[11][11];
    bool vis[11];
    void clear(){
        memset(x,0,sizeof(x));
        memset(vis,0,sizeof(vis));
    }
};


int a[N];
Flag flag[SQN];
int n,q;
int block_size,block_num;

void build(){
    block_size=(int)sqrt(n+0.000001);
    if(block_size<10) block_size=10;
    block_num=n/block_size+(n%block_size!=0);
    for(int i=0;i<block_num;i++) flag[i].clear();
}

void pushdown(int block_no){
    for(int i=1;i<=10;i++) if(flag[block_no].vis[i]) {
        int sta=block_no*block_size;
        for(int j=0;j<i;j++) {
            for(int k=sta+j;k<sta+block_size;k+=i) a[k]+=flag[block_no].x[i][j];
        }
    }
    flag[block_no].clear();
}


int query(int pos) {
    int x=pos/block_size;
    pushdown(x);
    return a[pos];
}


void update_block(int block_no,int sta,int k,int add){
    if(sta<k) flag[block_no].x[k][sta]+=add,flag[block_no].vis[k]=1;
}


int sft(int block_no,int l,int k) {
    int tmp=block_no*block_size;
    int ret=0;
    while(( (tmp-l)%k)!=0) {
        tmp++,ret++;
    }
    return ret;
}

void update(int l,int r,int k,int add){
    int lx=l/block_size;
    int rx=r/block_size;
    if(lx==rx){
        pushdown(lx);
        for(int i=l;i<=r;i+=k) a[i]+=add;
    }else{
        pushdown(lx);pushdown(rx);
        for(int i=l;i<(lx+1)*block_size;i+=k) a[i]+=add;
        for(int i=rx*block_size+sft(rx,l,k);i<=r;i+=k) a[i]+=add;
    }
    for(int i=lx+1;i<=rx-1;i++) {
        update_block(i,sft(i,l,k),k,add);
    }
}
int main() {
    while(scanf("%d",&n)!=EOF) {
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        build();
        scanf("%d",&q);
        while(q--){
            int cmd,l,r,k,add;
            scanf("%d",&cmd);
            if(cmd==1){
                scanf("%d%d%d%d",&l,&r,&k,&add);
                l--;r--;
                update(l,r,k,add);
            }else{
                scanf("%d",&k);
                printf("%d\n",query(k-1));
            }
        }
    }
    return 0;
}
posted @ 2012-09-08 23:05 编程菜菜 阅读(...) 评论(...) 编辑 收藏