洛谷 P1438 无聊的数列

来源:互联网 发布:云计算的具体应用 编辑:程序博客网 时间:2024/06/05 20:37

题目背景
无聊的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:
有没有巧妙的做法?

//看的狗哥的代码,不明白标记下放怎么不对#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;#define MAXN 100005struct SegMent_Tree{ int l,r,k,d,val; }tre[MAXN<<2];inline void read(int &x){    x=0; int f=1; char c=getchar();    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }    while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } x*=f;}void Modify(int u,int l,int r,int k,int d){    if(l<=tre[u].l&&tre[u].r<=r){        tre[u].k+= k+(tre[u].l-l)*d,tre[u].d+=d;        return ;    }    int Mid=tre[u].l+tre[u].r>>1;    if(l<=Mid) Modify(u<<1,l,r,k,d);    if(r>Mid) Modify(u<<1|1,l,r,k,d);}int Query(int u,int pos){    if(tre[u].l==tre[u].r) return tre[u].val+tre[u].k;    int ans=tre[u].k+tre[u].d*(pos-tre[u].l);    int Mid=tre[u].l+tre[u].r>>1;    if(pos<=Mid) return ans+Query(u<<1,pos);    else return ans+Query(u<<1|1,pos);}void Build(int u,int l,int r){    tre[u].l=l,tre[u].r=r,tre[u].k=0,tre[u].d=0;    if(l==r){ scanf("%d",&tre[u].val); return ; }    int Mid=l+r>>1;    Build(u<<1,l,Mid),Build(u<<1|1,Mid+1,r);    tre[u].val=tre[u<<1].val+tre[u<<1|1].val;}int main(){    int m,l,k,d,r,pos,opt,n;    scanf("%d%d",&n,&m);    Build(1,1,n);    while(m--){        scanf("%d",&opt);        if(m==3) int asd=0;        if(opt==1) scanf("%d%d%d%d",&l,&r,&k,&d),Modify(1,l,r,k,d);        else scanf("%d",&pos),printf("%d\n",Query(1,pos));    }    return 0;}
原创粉丝点击