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;
}