Q - 这是一道简单题
Time Limit: 100 MS Memory Limit: 64 MB
Submit Status
出题人Acnext
又要背锅了,他必须出一道大家都会做的简单题,如果有人做不出来他就得背锅,聪明的你能解决这道简单题让他避免背锅吗:
给出一个长nn的数列,以及nn个操作,操作涉及区间加法,单点查询
Input
第一行输入一个数字n,(1≤n≤50000)n,(1≤n≤50000)
第二行输入nn个正整数,第ii个数字为ai,(1≤ai≤109)ai,(1≤ai≤109),空格隔开
接下来输入nn行询问,每行输入四个数字opt,l,r,copt,l,r,c
若opt=0opt=0,表示将[l,r][l,r]的数字都加cc
若opt=1opt=1,表示询问arar的值(忽略l,cl,c)
Output
对于每次询问,输出一行代表答案
保证所有数据在int
范围内
Sample input and output
Sample Input | Sample Output |
---|---|
4 1 2 2 3 0 1 3 1 1 0 1 0 0 1 2 2 1 0 2 0 |
2 5 |
Hint
分块做法有加分哦
#include<algorithm> #include<cstdio> #include<iostream> using namespace std; struct SegmentTree { int l,r; long long sum, add; #define l(x) tree[x].l #define r(x) tree[x].r #define sum(x) tree[x].sum #define add(x) tree[x].add } tree[1000010*4]; int a[1000010]; long long n,m; void build(int p,int l,int r) { l(p)=l; r(p)=r; if(l==r) { sum(p)=a[l]; return; } int mid = (l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); sum(p)=sum(p*2+1)+sum(p*2); } void spread(int p) { if(add(p)) { sum(p*2)+=add(p)*(r(p*2)-l(p*2)+1); sum(p*2+1)+=add(p)*(r(p*2+1)-l(p*2+1)+1); add(p*2)+=add(p); add(p*2+1)+=add(p); add(p)=0; } } void change (int p, int l, int r, int d) { if(l<=l(p)&&r>=r(p)) { sum(p)+=(long long )d*(r(p)-l(p)+1); add(p)+=d; return; } spread(p); int mid=(l(p)+r(p))/2; if(l<=mid) { change(p*2,l,r,d); } if(r>mid) { change(p*2+1,l,r,d); } sum(p)=sum(p*2)+sum(p*2+1); } long long ask(int p, int l,int r) { if(l<=l(p)&&r>=r(p)) { return sum(p); } spread(p); int mid = (l(p)+r(p))/2; long long val = 0; if(l<=mid) val+=ask(p*2,l,r); if(r>mid) val+=ask(p*2+1,l,r); return val; } int main() { scanf("%lld",&n); for(int i=1;i<=n;i++) { scanf("%lld",a+i); } build(1,1,n); while(n--) { char op[2];long long l,r,v; scanf("%s%d%d%d",op,&l,&r,&v); if(op[0]=='0') { change(1,l,r,v); } else { printf("%lld\n",ask(1,r,r)); } } }