1080 线段树练习

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
 
题目描述 Description

一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。

输入描述 Input Description

输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。

输出描述 Output Description

共m行,每个整数

样例输入 Sample Input

6

4

5

6

2

1

3

4

1 3 5

2 1 4

1 1 9

2 2 6

样例输出 Sample Output

22

22

数据范围及提示 Data Size & Hint

1≤N≤100000, m≤10000 。

#include <cstdio>
#include <iostream>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=;
using namespace std;
int sum[maxn<<]; void PushUP(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];//将两条小区间合并成一个大区间
} void build(int l,int r,int rt)
{
if (l==r)//最底层的节点
{
scanf("%d",&sum[rt]);//读入节点的值
return;
}
int m=(l+r)>>;//分成两个区间
build(lson);//分别搞搞左右两个区间
build(rson);
PushUP(rt);//将最底层的节点的值传入上层节点
} void update(int p,int add,int l,int r,int rt)
{
if (l==r)//往最底层节点加上add
{
sum[rt]+=add;
return;
}
int m=(l+r)>>;//取中间节点
if (p<=m)update(p,add,lson);//找到节点的儿子并且是p的祖先的节点,递归到p
else update(p,add,rson);
PushUP(rt);//更新p祖先节点的值
} int query(int L,int R,int l,int r,int rt)//区间查询
{//L,R是要查询的区间和,l、r是目前的区间,rt是目前的节点
if (L<=l&&r<=R)
{
return sum[rt];//如果当前区间是所求区间的一部分,就加上这段区间
}
int m=(l+r)>>;//二分当前区间
int ret=;//为所求区间的数值和
if (L<=m)ret+=query(L,R,lson);//加上所需区间
if (R>m)ret+=query(L,R,rson);
return ret;
} int main()
{
int n,m;
scanf("%d",&n);//区间为1-n
build(,n,);//建树
int cz;
cin>>m;
while(m--)
{
scanf("%d",&cz);
int a,b;
scanf("%d%d",&a,&b);
if (cz==)printf("%d\n",query(a,b,,n,));//query 询问区间的总值
//else if (cz==3)update(a,-b,1,n,1);//sub 往第a个数里减b
else update(a,b,,n,);//往第a个数中加b
}
return ;
}

给你N个数,有两种操作

1:给区间[a,b]的所有数都增加X

2:询问第i个数是什么?

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

数据范围

1<=n<=100000

1<=q<=100000

#include <cstdio>
#include <iostream>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=;
using namespace std;
int sum[maxn<<]; void PushUP(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];//将两条小区间合并成一个大区间
} void build(int l,int r,int rt)
{
if (l==r)//最底层的节点
{
scanf("%d",&sum[rt]);//读入节点的值
return;
}
int m=(l+r)>>;//分成两个区间
build(lson);//分别搞搞左右两个区间
build(rson);
PushUP(rt);//将最底层的节点的值传入上层节点
} void update(int p,int add,int l,int r,int rt)
{
if (l==r)//往最底层节点加上add
{
sum[rt]+=add;
return;
}
int m=(l+r)>>;//取中间节点
if (p<=m)update(p,add,lson);//找到节点的儿子并且是p的祖先的节点,递归到p
else update(p,add,rson);
PushUP(rt);//更新p祖先节点的值
} int query(int L,int R,int l,int r,int rt)//区间查询
{//L,R是要查询的区间和,l、r是目前的区间,rt是目前的节点
if (L<=l&&r<=R)
{
return sum[rt];//如果当前区间是所求区间的一部分,就加上这段区间
}
int m=(l+r)>>;//二分当前区间
int ret=;//为所求区间的数值和
if (L<=m)ret+=query(L,R,lson);//加上所需区间
if (R>m)ret+=query(L,R,rson);
return ret;
} int main()
{
int n,m;
scanf("%d",&n);//区间为1-n
build(,n,);//建树
int cz;
cin>>m;
while(m--)
{
scanf("%d",&cz);
int a,b,c;
if (cz==)
{
cin>>a>>b>>c;
for(int i=a;i<=b;++i)
update(i,c,,n,);
}
else
{
cin>>a;
cout<<query(a,a,,n,)<<endl;
}
}
return ;
}
题目描述 Description

给你N个数,有两种操作:

1:给区间[a,b]的所有数增加X

2:询问区间[a,b]的数的和。

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,

再接下来一个正整数Q,每行表示操作的个数,

如果第一个数是1,后接3个正整数,

表示在区间[a,b]内每个数增加X,如果是2,

表示操作2询问区间[a,b]的和是多少。

pascal选手请不要使用readln读入

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 2 3

样例输出 Sample Output

9

数据范围及提示 Data Size & Hint

数据范围

1<=n<=200000

1<=q<=200000

 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 500005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
ll sum[N*];
int visit[N*];
void pushUp(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];
} void build(int l,int r,int rt)
{
visit[rt]=;
if(l==r)
{
scanf("%lld",&sum[rt]);
return ;
}
int m=(l+r)>>;
build(lson);
build(rson);
pushUp(rt);
} void pushDown(int rt,int d)
{
if(visit[rt]!=)
{ visit[rt<<]+=visit[rt];
visit[rt<<|]+=visit[rt];
sum[rt<<|]+=(ll)(d>>)*visit[rt];
sum[rt<<]+=(ll)(d-(d>>))*visit[rt];
visit[rt]=;
}
} void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l && R>=r)
{
visit[rt]+=c;
sum[rt]+=(r-l+)*c;
return ;
}
pushDown(rt,r-l+);
int m=(l+r)>>;
if(L<=m)
update(L,R,c,lson);
if(R>m)
update(L,R,c,rson);
pushUp(rt);
} ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
return sum[rt];
}
pushDown(rt,r-l+);
int m=(l+r)>>;
ll ret=;
if(L<=m)
ret+=query(L,R,lson);
if(R>m)
ret+=query(L,R,rson);
return ret;
} int main()
{
int n,q,a,b,c;
int s;
scanf("%d",&n);
build(,n,);
cin>>q;
while(q--)
{
scanf("%d",&s);
if(s==)
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,,n,);
}
else if(s==)
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(a,b,,n,));
}
}
return ;
}

codevs 线段树练习ⅠⅡⅢ的更多相关文章

  1. [codevs]线段树练习5

    http://codevs.cn/problem/4927/ #include <iostream> #include <cstdio> #include <algori ...

  2. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  3. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  4. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  5. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  6. codevs 1080 线段树练习

    链接:http://codevs.cn/problem/1080/ 先用树状数组水一发,再用线段树水一发 树状数组代码:84ms #include<cstdio> #include< ...

  7. 线段树练习 codevs 1080

    /* codevs 1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 一行N个方格,开 ...

  8. codevs 1080 线段树练习 CDQ分治

    codevs 1080 线段树练习 http://codevs.cn/problem/1080/  时间限制: 1 s  空间限制: 128000 KB   题目描述 Description 一行N个 ...

  9. 4163 hzwer与逆序对 (codevs + 权值线段树 + 求逆序对)

    题目链接:http://codevs.cn/problem/4163/ 题目:

随机推荐

  1. 并查集——poj2492(带权并查集入门)

    一.题目回顾 题目链接:传送门 题意:给定n只虫子,不同性别的可以在一起,相同性别的不能在一起.给你m对虫子,判断中间有没有同性别在一起的. 二.解题思路 种类并查集 和poj1073的本质一样 详见 ...

  2. 【iOS开发】动态添加子视图 UIView 的正确方法

    很多时候哥比较喜欢用代码添加视图,特别是要同时加很多UIView时,而且跟 xib 比起来代码更容易管理,在多人的项目中代码不容易 conflict. 但小牛哥最近发现很多新人都不太清楚正确的使用方法 ...

  3. IP数据报格式 及分组转发算法

    ip数据报分首部和数据两部分组成: 首部分为固定部分和可变部分 版本——占 4 位,指 IP 协议的版本 目前的 IP 协议版本号为 4 (即 IPv4) 首部长度——占 4 位,可表示的最大数值 是 ...

  4. C# 几种读取MAC地址的方法

    以下是收集的几种C#程序读取MAC地址的方法,示例中是读取所有网卡的MAC地址,如果仅需要读取其中一个,稍作修改即可. 1 通过IPConfig命令读取MAC地址 ///<summary> ...

  5. slf4j使用log4j学习笔记

    一,介绍 SLF4J 简单日记门面(Facade)SLF4J是为各种loging APIs提供一个简单统一的接口,从而使得最终用户能够在部署的时候配置自己希望的loging APIs实现. Loggi ...

  6. idea tomcat 启动报错 org.apache.catalina.core.StandardService.initInternal Failed to initialize connector

    org.apache.catalina.core.StandardService.initInternal Failed to initialize connector org.apache.cata ...

  7. Xcode 6.0中彻底关闭ARC

    对整个项目关闭ARCproject -> Build settings -> Apple LLVM complier 3.0 - Language -> objective-C Au ...

  8. WebApp之Meta标签总结

    在做WebApp的时候,少不了Meta标签引用,这里总结了下. <meta name="apple-touch-fullscreen" content="yes&q ...

  9. [洛谷P2044][NOI2012]随机数生成器

    题目大意:给你$m,a,c,X_0,n,g$,求$X_{n+1}=(a\cdot X_n+c) \bmod{m}$,最后输出对$g$取模 题解:矩阵快速幂+龟速乘,这里用了$long\;double$ ...

  10. [洛谷P3946] ことりのおやつ(小鸟的点心)

    题目大意:最短路,第$i$个点原有积雪$h_i$,极限雪高$l_i$(即雪超过极限雪高就不可以行走),每秒降雪$q$,ことり速度为$1m/s$,若时间大于$g$,则输出$wtnap wa kotori ...