CodeVS 1080 线段树练习 分块 块状数组
2016-02-02 10:27
363 查看
题意
给定序列a,支持两种操作:1. 单点修改
2. 区间求和
1≤N≤1000001\leq N\leq 100000
M≤10000M\leq 10000
分析
考虑分块。我们把连续的n√\sqrt n个元素放在一块,并保存所有值的和。
对于单点修改,找到对应块,修改对应点的值和块的和。
对于区间求和,注意分类讨论:
①当l,rl,r在同一块时,直接求和;
②当l,rl,r不在同一块时,
需要统计三种:ll到块尾,块头到rr,ll的下一块到rr的上一块的和。
还有注意要开long long。
代码
#include <cstdio> #include <cctype> #include <cmath> typedef long long Lint; const int N=100010; const int U=400; int n; int unit; struct Block { int a[U]; Lint sum; }b[U]; int btot; inline int read(void) { int x=0,f=1; char c=getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-1; for (;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } int m; inline void update(int loc,int add) { int lb=(loc-1)/unit+1,lc=loc-(lb-1)*unit; b[lb].a[lc]+=add; b[lb].sum+=add; } Lint query(int l,int r) { int lb=(l-1)/unit+1,lc=l-(lb-1)*unit; int rb=(r-1)/unit+1,rc=r-(rb-1)*unit; Lint sum=0; if (lb==rb) for (int i=lc;i<=rc;i++) sum+=b[lb].a[i]; else { for (int i=lc;i<=unit;i++) sum+=b[lb].a[i]; for (int i=lb+1;i<=rb-1;i++) sum+=b[i].sum; for (int i=1;i<=rc;i++) sum+=b[rb].a[i]; } return sum; } int main(void) { n=read(); unit=(int)sqrt(n); int nowcur=unit; int x; for (int i=1;i<=n;i++) { if (nowcur==unit) btot++,nowcur=0; x=read(); b[btot].sum+=x; b[btot].a[++nowcur]=x; } int k,y,z; m=read(); for (int i=1;i<=m;i++) { k=read(),y=read(),z=read(); if (k==1) update(y,z); else printf("%d\n",query(y,z)); } return 0; }
相关文章推荐
- oracle唯一索引与普通索引的区别和联系以及using index用法
- mongodb group php 操作
- spring源码学习之二 XmlWebApplicationContext类结构概述
- Hbase笔记 - 快速安装(单机模式)
- canvas画各种图形
- javascript的闭包
- 软件测试方法汇总
- win7 iis 配置PHP5.3.27实践记录
- LeetCode 303. Range Sum Query - Immutable
- vc编译选项
- MongoDB 删除文档
- 【给你几个使用Xamarin的理由】
- 各种渲染软件设计理论详解
- 【LCT】BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊
- MYSQL 下补充拳路对应的绣像图地址
- Cocos2d-x3.2 Sprite精灵类的创建与设置
- 文件系统
- centos7 关闭firewall防火墙指令以及更换安装iptables并配置
- JDBC处理器和BeanShell取样器的组合应用
- Java实现根据属性排序输出对象