http://acm.hdu.edu.cn/showproblem.php?pid=4267
01給數組Ai 有初始值 現有兩個操作
1.給區間[a,b]中滿足(i - a) % k == 0的每一個Ai的值加c
2 詢問Ai的值
形成線段樹的想法,很明顯,由於k<=10,值非常小,所以,可以在節點維護間隔值分別爲1-10的情況,總共55中情況
比賽的時候sb的直接開add[10][10]...一直mle,然後改成動態分配之後tle,尼瑪哪知道開add[55]就正好合適。。。。
什麼都不說了,貼代碼。。。鬱悶。。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
const int N=50002;
int n, m;
struct node
{
bool flag;
int l, r;
int val;
int add[55];
void reset()
{
memset(add, 0, sizeof(add));
flag = false;
}
} a[N*4];
int b[N], kk, cc;
void build(int l, int r, int p)
{
a[p].l = l;
a[p].r = r;
a[p].reset();
if(l==r)
{
a[p].val = b[l];
return;
}
int mid = (l+r)>>1;
build(l, mid, p*2);
build(mid+1, r, p*2+1);
}
inline int ijToNum(int i, int j)
{
return (i*(i+1))/2 + j;
}
inline void down(int p)
{
if (a[p].flag == true)
{
int i, j;
for (i = 0; i < 10; i++)
{
int ii = i+1;
for (j = 0; j <= i; j++)
{
if (a[p].add[ijToNum(i, j)] != 0)
{
a[p*2].add[ijToNum(i, j)] += a[p].add[ijToNum(i, j)];
a[p*2].flag = true;
a[p*2+1].add[ijToNum(i, (ii*50001-(a[p*2].r-a[p*2].l+1-j) % ii ) % ii )] += a[p].add[ijToNum(i, j)];
//這裏一定要注意左半部分已經產生的偏移對後半部分的影響。。。即j的用處。。。
a[p*2+1].flag = true;
}
}
}
a[p].reset();
}
}
void update(int l, int r, int p, int ki)
{
if(a[p].l==l && a[p].r==r)
{
//a[p].add[kk-1][ki] += cc;
a[p].add[ijToNum(kk-1, ki)] += cc;
a[p].flag = true;
return;
}
//down(p);
int mid = (a[p].l+a[p].r)>>1;
if(r<=mid)
update(l, r, p*2, ki);
else if(l>mid)
update(l, r, p*2+1, ki);
else
{
update(l, mid, p*2, ki);
update(mid+1, r, p*2+1, (kk*50001-(mid-l+1-ki)%kk)%kk ); //這裏開始搞成a[p].r - a[p].l + 1了。。。。
}
}
int query(int l, int r, int p)
{
if(a[p].l==l && a[p].r==r)
{
if (a[p].flag == true)
{
for (int i = 0; i < 10; i++)
{
//a[p].val += a[p].add[i][0];
a[p].val += a[p].add[ijToNum(i, 0)];
//a[p].add[i][0] = 0;
a[p].add[ijToNum(i, 0)] = 0;
}
a[p].flag = false;
}
return a[p].val;
}
down(p);
int mid = (a[p].l+a[p].r)>>1;
if(r<=mid)
return query(l, r, p*2);
else if(l>mid)
return query(l, r, p*2+1);
}
int main()
{
int op, aa, bb;
while(scanf("%d", &n)!=EOF)
{
for (int i = 1; i <= n; i++)
{
scanf("%d", &b[i]);
}
build(1, n, 1);
scanf("%d", &m);
//printf("Case #%d:\n", cas1++);
while(m--)
{
scanf("%d", &op);
if (op == 1)
{
scanf("%d %d %d %d", &aa, &bb, &kk, &cc);
update(aa, bb, 1, 0);
}
else
{
scanf("%d", &aa);
printf("%d\n", query(aa, aa, 1));
}
}
}
return 0;
}