![]() | ||||||||||
| ||||||||||
A Simple Problem with IntegersTime Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3544 Accepted Submission(s): 1094
Problem Description
Let A1, A2, ... , AN be N elements. You need to deal with two kinds of operations. One type of operation is to add a given number to a few numbers in a given interval. The other is to query the value of some element.
Input
There are a lot of test cases.
The first line contains an integer N. (1 <= N <= 50000) The second line contains N numbers which are the initial values of A1, A2, ... , AN. (-10,000,000 <= the initial value of Ai <= 10,000,000) The third line contains an integer Q. (1 <= Q <= 50000) Each of the following Q lines represents an operation. "1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0. (1 <= a <= b <= N, 1 <= k <= 10, -1,000 <= c <= 1,000) "2 a" means querying the value of Aa. (1 <= a <= N)
Output
For each test case, output several lines to answer all query operations.
Sample Input
Sample Output
|
又是一道神奇的题目。。。
这个题是对区间内不同的数加上一个值,但线段树只能维护连续的区间,所以这里我们按照k进行分组,根据(i-a)%k==0 --> i%k=a%k。
分组后一共有55中情况:
1,2,3,4,5......
1,3,5,7,9......
2,4,6,8,10....
1,4,7,10,13...
2,5,9,12,15...
3,6,10,13,16...
这样输入a,b,就可以定位到tree[k][a%k]这一组,然后对组内进行成段更新,线段树和树状数组都可以。
Tips:
树状数组的优势是方便动态求值和更新..
可惜树状数组是单点更新
倒是有个方法可以快速成段更新
就是在区间[a, b]内更新+x就在a的位置+x 然后在b+1的位置-x
求某点a的值就是求数组中1~a的和..
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=50010;
int n,a[maxn];
struct BIT
{
int val[maxn];
void clear(){memset(val,0,sizeof(val));}
int lowbit(int x)
{
return x&(-x);
}
void update(int s,int e,int x)
{
while(e>0)
{
val[e]+=x;
e-=lowbit(e);
}
s--;
while(s>0)
{
val[s]-=x;
s-=lowbit(s);
}
}
int getsum(int x)
{
int sum=0;
while(x<maxn)
{
sum+=val[x];
x+=lowbit(x);
}
return sum;
}
}tree[12][12];
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=0;i<=10;i++)
for(int j=0;j<=10;j++)tree[i][j].clear();
int q;
scanf("%d",&q);
while(q--)
{
int op,l,r,k,x;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d%d",&l,&r,&k,&x);
tree[k][l%k].update(l/k+1,l/k+(r-l)/k+1,x);
}
else
{
scanf("%d",&x);
int sum=0;
for(int i=1;i<=10;i++)
sum+=tree[i][x%i].getsum(x/i+1);
printf("%d\n",sum+a[x]);
}
}
}
return 0;
}
线段树代码(别人的):
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<vector>
using namespace std;
const int N=50010;
int sum[N<<2][55];
int col[N<<2],res[N];
#define lson l,mid, rt << 1
#define rson mid+1,r,rt << 1 | 1
int mod,LL;
int shunxu[11][11];
void PushDown(int rt)
{
if(col[rt])
{
col[rt<<1] += col[rt];
col[rt<<1|1] += col[rt];
col[rt]=0;
for(int i=0; i<55; i++)
{
sum[rt<<1][i] += sum[rt][i];
sum[rt<<1|1][i] += sum[rt][i] ;
sum[rt][i]=0;
}
}
}
void build(int l,int r,int rt)
{
col[rt]=0;
memset(sum[rt],0,sizeof(sum[rt]));
if(l==r)
return;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int val,int l,int r,int rt)
{
if(l==L&&r==R)
{
col[rt]+=val;
sum[rt][shunxu[mod][LL%mod]]+=val;
return ;
}
PushDown(rt);
int mid=(l+r)>>1;
if(R<=mid)update(L,R,val,lson);
else if(L>mid)update(L,R,val,rson);
else
{
update(L,mid,val,lson);
update(mid+1,R,val,rson);
}
}
int query(int l,int r,int rt,int m)
{
if(l==r)
{
int d=0;
for(int i=1; i<=10; i++)
d += sum[rt][shunxu[i][m%i]];
return d+res[l];
}
int mid=(l+r)>>1;
PushDown(rt);
if(m<=mid)
return query(lson,m);
else return query(rson,m);
}
int main()
{
int n,q,cc=0;
for(int i=1; i<=10; i++)
for(int j=0; j<i; j++)
shunxu[i][j]=cc++;
while(~scanf("%d",&n))
{
build(1,n,1);
int q;
for(int i=1; i<=n; i++)
scanf("%d",&res[i]);
scanf("%d",&q);
int kk,aa,RR,k,val;
while(q--)
{
scanf("%d",&kk);
if(kk==2)
{
scanf("%d",&aa);
printf("%d\n",query(1,n,1,aa));
}
else if(kk==1)
{
scanf("%d%d%d%d",&LL,&RR,&mod,&val);
update(LL,RR,val,1,n,1);
}
}
}
return 0;
}