POJ 3468 A Simple Problem with Integers【线段树(结构体)】
2015-10-11 18:55
435 查看
A Simple Problem with Integers
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 80222 | Accepted: 24761 | |
Case Time Limit: 2000MS |
You have N integers, A1,
A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval.
The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1,
A2, ... , AN. -1000000000 ≤
Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa,
Aa+1, ... ,
Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa,
Aa+1, ... ,
Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
The sums may exceed the range of 32-bit integers
题目大意就是说,n个数,然后又q中操作,C a b c代表从第a个数到第b个数每个都加上c ,Q a b代表查询从第a个数到第b个数的总和。然后数据会超32位。结构体记录端点和总和以及标记一下该区间是否要更新。在更新时标记一下,而不实际改变值,在查询时,若要更新,先把更新标记传给两个子区间,然后改变该区间的值并取消标记。
#include <iostream> #include<cstdio> #include<cstring> #define maxn 100000+10 #define ll long long using namespace std; struct lnode { ll left,right,sum,mark; }; lnode num[maxn<<2]; ll rec[maxn]; ll build(ll o,ll l,ll r) { num[o].left=l; num[o].right=r; num[o].mark=0; if(l==r) return num[o].sum=rec[l]; ll mid=(num[o].left+num[o].right)>>1; return num[o].sum=build(o<<1,l,mid)+build(o<<1|1,mid+1,r); } void update(ll o,ll l,ll r,ll v) { if(l<=num[o].left&&r>=num[o].right) { num[o].mark+=v; return ; } num[o].sum+=v*(r-l+1); ll mid=(num[o].left+num[o].right)>>1; if(r<=mid) update(o<<1,l,r,v); else if(l>mid) update(o<<1|1,l,r,v); else { update(o<<1,l,mid,v); update(o<<1|1,mid+1,r,v); } } ll query(ll o,ll l,ll r) { if(l<=num[o].left&&r>=num[o].right) return num[o].sum+num[o].mark*(r-l+1); if(num[o].mark) { num[o<<1].mark+=num[o].mark; num[o<<1|1].mark+=num[o].mark; num[o].sum+=num[o].mark*(num[o].right-num[o].left+1); num[o].mark=0; } ll mid=(num[o].left+num[o].right)>>1; ll ans=0; if(r<=mid) ans+=query(o<<1,l,r); else if(l>mid) ans+=query(o<<1|1,l,r); else ans+=query(o<<1,l,mid)+query(o<<1|1,mid+1,r); return ans; } int main() { ll n,q,a,b,c; char s[5]; while(~scanf("%lld%lld",&n,&q)) { for(int i=1;i<=n;++i) scanf("%lld",&rec[i]); build(1,1,n); while(q--) { scanf("%s",s); if(s[0]=='C') { scanf("%lld%lld%lld",&a,&b,&c); update(1,a,b,c); } else { scanf("%lld%lld",&a,&b); printf("%lld\n",query(1,a,b)); } } } return 0; }
相关文章推荐
- ListView setOnItemClickListener 点击无效
- 【转】ibatis的简介与初步搭建应用
- 使用Microsoft Azure Backup恢复Hyper-V数据
- “艰难的”第一步
- Rhel7 配置lvm
- 科研有方——英文论写作
- 对10个数进行排序
- 第四周项目5--猴子选大王
- LBS(Location Based Service)
- 南洋理工ACM阶乘因式分解(二)070
- 傅里叶分析之掐死教程(完整版)
- 凸包
- cgi fast-cgi fpm概念
- 约瑟夫问题
- 【五校联考5day1】登山
- 大数操作(BigInteger类、BigDecimal类)
- fedora 使用音乐播放器
- gcc的使用
- 第二章 Winsock编程接口(2)
- 安德鲁斯,最直接的方法,实现了上拉刷新下拉加载很多其他的