[cdoj 1344]树状数组区间加等差数列
题目链接:http://acm.uestc.edu.cn/#/problem/show/1344
区间加等差数列本质上就是区间修改区间查询,本来想用线段树做,结果这个题就是卡空间和时间……不得已学了区间修改区间查询的树状数组。
#include<bits/stdc++.h> using namespace std; const int maxn=1000005; const int md=772002+233; int a[maxn]; int N; int tree[maxn]; int tree2[maxn]; int lowbit(int x) { return x&-x; } void add(int tree[],int k,int x) { while (k<=N) { tree[k]=(tree[k]+x)%md; k+=lowbit(k); } } int query(int tree[],int k) { int res=0; while (k) { res=(res+tree[k])%md; k-=lowbit(k); } return res; } void add(int l,int r,int x) { add(tree,l,x); add(tree,r+1,((-x)%md+md)%md); add(tree2,l,1ll*(l-1)*x%md); add(tree2,r+1,(1ll*r*(-x)%md+md)%md); } int querysum(int k) { return ((1ll*query(tree,k)*k%md-query(tree2,k))%md+md)%md; } void addad(int l,int r,int a0,int d) { add(l,l,a0); if (l+1<=r) add(l+1,r,d); add(r+1,r+1,(-(a0+1ll*(r-l)*d%md)%md+md)%md); } int queryad(int k) { return querysum(k); } void init(int n) { N=n+2; for (int i=0;i<=N;i++) tree[i]=tree2[i]=0; } int main() { int n,q; scanf("%d%d",&n,&q); for (int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]%=md; init(n); while (q--) { int op; scanf("%d",&op); if (op==1) { int x,y; scanf("%d%d",&x,&y); int l=x; int r=min(x+y-1,n); addad(l,r,y,-1); } else { int x; scanf("%d",&x); printf("%d\n",(a[x]+queryad(x))%md); } } return 0; }