博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2471. [EZOI 2016]源氏的数学课
阅读量:5033 次
发布时间:2019-06-12

本文共 3329 字,大约阅读时间需要 11 分钟。

                                             

【题目描述】

给定一个数列,有如下两种操作:

1:将其中的一个数加上s(s为整数)

2:给定区间[l,r],求al* (r-l+1) + al-1*(r-l)+ ...... + ar-1*2 + a1*1的值。

即:

$\Large \sum_{i=l}^{r} a_i·(r-i+1)$

【输入格式】

第一行有2个数n,q,分别表示Teacher数列中数的个数以及操作次数。

接下来的一行有n个数,第i个数表示$a_i$。

再接下来q行,每行三个数;第一个数是order。如果order=1,那么接下来两个数:x, s,即把$a_x$加上s;如果order=2,那么接下来两个数:l, r,即求这一段区间源氏要求的答案。

【输出格式】

对于每一个询问(order=2)输出所求答案

【样例输入】

5 3

2 4 1 3 5

2 2 4

1 2 3

2 2 4

【样例输出】

17

26

【提示】

不保证数列全为正数,但保证是整数。

$n<=100000, q<=100000$,保证答案不超过long long (int64) 范围,保证数据有梯度

【来源】

未知

 

维护al* (r-l+1) + al-1*(r-l)+ ...... + ar-1*2 + a1*1 这个序列 

我们可以发现 这个和前缀和序列很相似 

于是我们可以 考虑一下前缀和 

 

S10:  a10+a9 + a8 + a7 + a6 + a+ a+ a+ a+ a1

S9:            a9 + a8 + a7 + a6 + a+ a+ a+ a+ a1

S8:         a8 + a7 + a6 + a+ a+ a+ a+ a1

S7:         a7 + a6 + a+ a+ a+ a+ a1

S6:              a6 + a+ a+ a+ a+ a1

S5:              a+ a+ a+ a+ a1

S4:              a+ a+ a+ a1

S3:                a+ a+ a1

S2:                   a+ a1

S1:                     a1

 

显然 要查询[6,10] 的话 需要S6+S7+S8+S9+S10-(S5*5) //5为[6,10] 的区间长度

我们可以用线段树维护输入序列前缀和的区间和  

单点修改的话 就成了区间修改 

修改 从当前位置一直到n

 

1 #include 
2 #include
3 4 typedef long long LL; 5 6 const int MAXN=100010; 7 8 int n,q; 9 10 LL a[MAXN];11 12 struct SgtmentTree {13 int l,r;14 int tag;15 LL sum;16 };17 SgtmentTree t[MAXN<<2];18 19 inline void read(int&x) {20 int f=1;register char c=getchar();21 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());22 for(;isdigit(c);x=x*10+c-48,c=getchar());23 x=x*f;24 }25 26 inline void down(int now) {27 t[now<<1].tag+=t[now].tag;28 t[now<<1|1].tag+=t[now].tag;29 t[now<<1].sum+=(t[now<<1].r-t[now].l+1)*t[now].tag;30 t[now<<1|1].sum+=(t[now<<1|1].r-t[now<<1|1].l+1)*t[now].tag;31 t[now].tag=0;32 }33 34 void build_tree(int now,int l,int r) {35 t[now].l=l;t[now].r=r;36 if(l==r) {37 t[now].sum=a[l];38 return;39 }40 int mid=(l+r)>>1;41 build_tree(now<<1,l,mid);42 build_tree(now<<1|1,mid+1,r);43 t[now].sum=t[now<<1].sum+t[now<<1|1].sum;44 }45 46 void modify(int now,int l,int r,int v) {47 if(l<=t[now].l&&r>=t[now].r) {48 t[now].sum+=(LL)(t[now].r-t[now].l+1)*v;49 t[now].tag+=v;50 return;51 }52 if(t[now].tag) down(now);53 int mid=(t[now].l+t[now].r)>>1;54 if(l<=mid) modify(now<<1,l,r,v);55 if(r>mid) modify(now<<1|1,l,r,v);56 t[now].sum=t[now<<1].sum+t[now<<1|1].sum;57 }58 59 LL query(int now,int l,int r) {60 if(l<=t[now].l&&r>=t[now].r) return t[now].sum;61 LL ans=0;62 if(t[now].tag) down(now);63 int mid=(t[now].l+t[now].r)>>1;64 if(l<=mid) ans+=query(now<<1,l,r);65 if(r>mid) ans+=query(now<<1|1,l,r);66 return ans;67 }68 69 int hh() {70 freopen("overwatch.in","r",stdin);71 freopen("overwatch.out","w",stdout);72 read(n);read(q);73 for(int x,i=1;i<=n;++i) read(x),a[i]+=a[i-1]+x;74 build_tree(1,1,n);75 for(int type,x,y,i=1;i<=q;++i) {76 read(type);read(x);read(y);77 if(type==1) modify(1,x,n,y);78 else {79 LL ans=0;80 ans=query(1,x,y)-query(1,x-1,x-1)*(y-x+1);81 printf("%lld\n",ans);82 }83 }84 return 0;85 }86 87 int sb=hh();88 int main(int argc,char**argv) {;}
代码

 

转载于:https://www.cnblogs.com/whistle13326/p/7503741.html

你可能感兴趣的文章
JSP 页面中插入图片
查看>>
[网络收集]showModalDialog和showModelessDialog区别
查看>>
[Canvas]Running Horse
查看>>
OC-runtime
查看>>
格式化输入输出和分支语句
查看>>
第三次作业:处理器管理与进程调度
查看>>
详解log4j2(上) - 从基础到实战
查看>>
Log4j日志管理的简单实例
查看>>
VS2013找不到SDKDDKVer.h
查看>>
设置Webdriver启动chrome为默认用户的配置信息
查看>>
[Tips]Javascrip计算文件行数
查看>>
Java开发小技巧(三):Maven多工程依赖项目
查看>>
python QRcode
查看>>
AHOI 2009 (BZOJ1798)维护序列 seq (线段树好题?)
查看>>
2019牛客暑期多校训练营(第五场)H subsequence 2(拓扑排序)
查看>>
第十七周博客作业<西北师范大学|李晓婷>
查看>>
[Err] 1136 - Column count doesn&#39;t match value count at row 1
查看>>
4.3dotnet watch run「深入浅出ASP.NET Core系列」
查看>>
iOS开发之版本控制(SVN)
查看>>
http
查看>>