线段树模板
线段树模板
HDU - 1166 - 敌兵布阵
本题为单点修改+区间查询 求和
#include <cstdio>
// #include <cstdlib>
using namespace std;
#define N (50000+5)
int arr[N];
int tree[N<<2];
void push_up(int root){ // 向上传播
tree[root] = tree[root<<1] + tree[root<<1|1];
}
void build_tree(int left,int right,int root){
if(left == right){
tree[root] = arr[left];
}else{
int mid = (left+right)>>1;
build_tree(left,mid,root<<1);
build_tree(mid+1,right,root<<1|1);
push_up(root);
}
}
void update(int left,int right,int root,int pos,int delta){ // 单点修改
if(left == right){
tree[root] += delta;
}else{
int mid = (left+right)>>1;
if(pos <= mid){
update(left,mid,root<<1,pos,delta);
}else{
update(mid+1,right,root<<1|1,pos,delta);
}
push_up(root);
}
}
int query(int left,int right,int root,int ask_left,int ask_right){
if(ask_right < left || ask_left > right){ // 待查询区间与当前区间交集为空
return 0;
}
if(left >= ask_left && ask_right >= right){ // 待查询区间包含当前区间
return tree[root];
}
int mid = (left+right)>>1;
return query(left,mid,root<<1,ask_left,ask_right) + query(mid+1,right,root<<1|1,ask_left,ask_right);
}
int main(){
int T;
scanf("%d",&T);
for(int g = 1; g <= T; g++){
printf("Case %d:\n",g);
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&arr[i]);
}
build_tree(1,n,1);
char cmd[10];
int i,j;
while(1){
scanf("%s",cmd);
if(cmd[0] == 'Q'){
scanf("%d%d",&i,&j);
printf("%d\n",query(1,n,1,i,j));
}else if(cmd[0] == 'A'){
scanf("%d%d",&i,&j);
update(1,n,1,i,j);
}else if(cmd[0] == 'S'){
scanf("%d%d",&i,&j);
update(1,n,1,i,-j);
}else{
break;
}
}
}
// system("pause");
return 0;
}
HDU - 1754 -I Hate It
本题为单点修改+区间查询 最值
#include <cstdio>
#include <cstdlib>
using namespace std;
#define N (200000+5)
#define MAX(a,b) (a>b?a:b)
int arr[N];
int tree[N<<2];
void push_up(int root){ // 向上传播
int a = tree[root<<1];
int b = tree[root<<1|1];
tree[root] = MAX(a,b);
}
void build_tree(int left,int right,int root){
if(left == right){
tree[root] = arr[left];
}else{
int mid = (left+right)>>1;
build_tree(left,mid,root<<1);
build_tree(mid+1,right,root<<1|1);
push_up(root);
}
}
void update(int left,int right,int root,int pos,int delta){ // 单点修改
if(left == right){
tree[root] = delta;
}else{
int mid = (left+right)>>1;
if(pos <= mid){
update(left,mid,root<<1,pos,delta);
}else{
update(mid+1,right,root<<1|1,pos,delta);
}
push_up(root);
}
}
int query(int left,int right,int root,int ask_left,int ask_right){
if(ask_right < left || ask_left > right){ // 待查询区间与当前区间交集为空
return 0;
}
if(left >= ask_left && ask_right >= right){ // 待查询区间包含当前区间
return tree[root];
}
int mid = (left+right)>>1;
int ll = query(left,mid,root<<1,ask_left,ask_right);
int rr = query(mid+1,right,root<<1|1,ask_left,ask_right);
return MAX(ll,rr);
}
int main(){
int n,q;
while(scanf("%d%d",&n,&q)!=EOF){
for(int i = 1; i <= n; i++){
scanf("%d",&arr[i]);
}
build_tree(1,n,1);
char cmd[10];
int i,j;
while(q--){
scanf("%s",cmd);
if(cmd[0] == 'Q'){
scanf("%d%d",&i,&j);
printf("%d\n",query(1,n,1,i,j));
}else{
scanf("%d%d",&i,&j);
update(1,n,1,i,j);
}
}
}
// system("pause");
return 0;
}
POJ - 3468 - A Simple Problem With Integers
注意一点:
只要某个结点的祖先结点没有lazy标记,那么这个结点的值就是正确的
当访问一个到一个有lazy标记的结点,就顺便将它的lazy标记传播到下一层
#include <cstdio>
// #include <cstdlib>
using namespace std;
#define N 100000+5
typedef long long ll;
ll arr[N];
ll tree[N<<2];
ll lazy[N<<2];
void push_up(int root){ // 向上传播,更新根节点的值
tree[root] = tree[root<<1] + tree[root<<1|1];
}
void push_down(int left,int right,int root){ // lazy标记向下传播
if(lazy[root]){
int mid = (left+right)>>1;
int left_root = root<<1;
int right_root = root<<1|1;
tree[left_root] += lazy[root] * (mid-left+1); // 更新子结点的值,但根结点的值还未更新,还需要push_up操作
tree[right_root] += lazy[root] * (right-mid);
lazy[left_root] += lazy[root]; // lazy标记向下传播
lazy[right_root] += lazy[root];
lazy[root] = 0;
}
}
void build_tree(int left,int right,int root){
if(left == right){
tree[root] = arr[left];
}else{
int mid = left+right>>1;
build_tree(left,mid,root<<1);
build_tree(mid+1,right,root<<1|1);
push_up(root);
}
}
void update(int left,int right,int root,int update_left,int update_right,ll delta){
if(update_left <= left && update_right >= right){ // 更新区间包含当前区间
tree[root] += delta * (right-left+1);
lazy[root] += delta;
}else{ // 更新区间不能包含当前区间
int mid = (left+right)>>1;
push_down(left,right,root);
if(update_left <= mid){ // 在左子树中存在更新区间
update(left,mid,root<<1,update_left,update_right,delta);
}
if(update_right > mid){ // 在右子树中存在更新区间
update(mid+1,right,root<<1|1,update_left,update_right,delta);
}
push_up(root);
}
}
ll query(int left,int right,int root,int query_left,int query_right){
if(query_left <= left && query_right >= right){
return tree[root];
}else{
push_down(left,right,root);
int mid = (left+right)>>1;
ll ans = 0;
if(query_left <= mid){
ans += query(left,mid,root<<1,query_left,query_right);
}
if(query_right > mid){
ans += query(mid+1,right,root<<1|1,query_left,query_right);
}
return ans;
}
}
int main(){
int n,q;
int l,r;
ll delta;
char cmd[5];
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; i++){
scanf("%lld",&arr[i]);
}
build_tree(1,n,1);
while(q--){
scanf("%s",cmd);
if(cmd[0] == 'Q'){
scanf("%d%d",&l,&r);
printf("%lld\n",query(1,n,1,l,r));
}else{
scanf("%d%d%lld",&l,&r,&delta);
update(1,n,1,l,r,delta);
}
}
// system("pause");
return 0;
}
---- suffer now and live the rest of your life as a champion ----