P1438 无聊的数列
题目背景
无聊的YYB总喜欢搞出一些正常人无法搞出的东西。有一天,无聊的YYB想出了一道无聊的题:无聊的数列。。。(K峰:这题不是傻X题吗)
题目描述
维护一个数列{a[i]},支持两种操作:
1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,
a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。
2、2 P:询问序列的第P个数的值a[P]。
输入输出格式
输入格式:
第一行两个整数数n,m,表示数列长度和操作个数。
第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。
接下来的m行,表示m个操作,有两种形式:
1 L R K D
2 P 字母意义见描述(L≤R)。
输出格式:
对于每个询问,输出答案,每个答案占一行。
输入输出样例
输入样例#1:
5 2 1 2 3 4 5 1 2 4 1 2 2 3
输出样例#1:
6
说明
数据规模:
0≤n,m≤100000
|a[i]|,|K|,|D|≤200
Hint:
有没有巧妙的做法?
1 /* 2 其实并不是维护一个等差序列 3 只需要维护l~r区间的首项 k 和公差 d 就好了 4 l~r 的子区间 x~y 的首项 k‘=k+d*(x-l); 5 d‘=d; 6 查询的时候 不要把标记忘了 其实标记不需要下放 7 但是 这题有毒 我用读入优化 2个TLE 8 换成scanf结果就AC了 9 */ 10 #include <ctype.h> 11 #include <cstdio> 12 13 const int MAXN=100010; 14 15 struct node { 16 int l,r; 17 int sum; 18 int k,d; 19 }; 20 node t[MAXN<<2]; 21 22 int n,m,k,d; 23 24 int a[MAXN]; 25 26 inline void build_tree(int now,int l,int r) { 27 t[now].l=l,t[now].r=r; 28 if(l==r) { 29 scanf("%d",&t[now].sum); 30 return; 31 } 32 int mid=(l+r)>>1; 33 build_tree(now<<1,l,mid); 34 build_tree(now<<1|1,mid+1,r); 35 } 36 37 void modify(int now,int l,int r) { 38 if(l<=t[now].l&&r>=t[now].r) { 39 t[now].k+=k+d*(t[now].l-l); 40 t[now].d+=d; 41 return; 42 } 43 int mid=(t[now].l+t[now].r)>>1; 44 if(l<=mid) modify(now<<1,l,r); 45 if(r>mid) modify(now<<1|1,l,r); 46 } 47 48 int query(int now,int pos) { 49 if(t[now].l==t[now].r) return t[now].sum+t[now].k; 50 int ans=t[now].k+t[now].d*(pos-t[now].l); 51 int mid=(t[now].l+t[now].r)>>1; 52 if(pos<=mid) return ans+query(now<<1,pos); 53 if(pos>mid) return ans+query(now<<1|1,pos); 54 } 55 56 int hh() { 57 int flag,l,r; 58 scanf("%d%d",&n,&m); 59 build_tree(1,1,n); 60 for(int i=1;i<=m;++i) { 61 scanf("%d",&flag); 62 if(flag==1) { 63 scanf("%d%d%d%d",&l,&r,&k,&d); 64 modify(1,l,r); 65 } 66 else { 67 scanf("%d",&l); 68 printf("%d\n",query(1,l)); 69 } 70 } 71 } 72 73 int sb=hh(); 74 int main() {;}
代码
时间: 2024-11-05 11:47:50