第六周周任务——线段树的运用

第六周周任务——线段树的运用

1.敌兵布阵 hdoj1166

单点增减,区间求和

线段树基础的模板题,适合新手学习

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <cmath>
//#define int long long
#define Mod 1000000007
#define pi (acos(-1))
#define INF 0x3f3f3f3f3f
#define Maxn 50005
using namespace std;
void build_tree(int arr[], int tree[], int node, int start, int end){
 if( start == end )
 {
  tree[node]=arr[start];
 }
 else
 { 
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  build_tree(arr, tree, left_node , start, mid);
  build_tree(arr, tree, right_node, mid+1, end);
  tree[node]=tree[left_node]+tree[right_node];
 } 
} 
void updata_tree(int arr[], int tree[], int node, int start, int end, int loc, int val){
 if( start == end ){
  arr[loc]=val;
  tree[node]=val;
 }
 else
 {
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  if( loc >= start && loc <= mid)
   updata_tree(arr, tree, left_node , start, mid, loc, val);
  else
   updata_tree(arr, tree, right_node, mid+1, end, loc, val);
  tree[node]=tree[left_node]+tree[right_node];
 }
}
int query_tree(int arr[], int tree[], int node, int start, int end, int L, int R){
 printf("****\n");
 if( R < start || L > end )
  return 0;
 else if( start >= L && end <= R )
  return tree[node];
 else if( start == end )
  return tree[start];
 else{
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  int sum_left  = query_tree(arr, tree, left_node , start, mid, L, R);
  int sum_right = query_tree(arr, tree, right_node, mid+1, end, L, R);
  return sum_left+sum_right;
 }
}
signed main(){
 int T;
 scanf("%d",&T);
 for(int k = 1 ; k <= T ; k ++ ){
  printf("Case %d:\n",k);
  int n;
  char opt[10];
  int arr[Maxn]={0};
  scanf("%d",&n);
  for(int i = 1 ; i <= n ; i ++ )
  scanf("%d",&arr[i]);
  int tree[4*Maxn]={0};
  //建树 
  build_tree(arr,tree,1,1,n);
//  for(int i = 1 ; i <= 31 ; i ++)
//  printf("tree[%d] = %d\n",i,tree[i]);
  while(~scanf("%s",opt)){
//   for(int i = 1 ; i <= 31 ; i ++)
//  printf("tree[%d] = %d\n",i,tree[i]);
   int l,r;
   if(!strcmp(opt,"End")) break;
   if(!strcmp(opt,"Query")){ 
    scanf("%d%d",&l,&r);
    printf("%d\n",query_tree(arr, tree, 1, 1, n, l, r));//printf("****\n");
   }
   else if(!strcmp(opt,"Add"))
   {
    
    scanf("%d%d",&l,&r);
    updata_tree(arr, tree, 1, 1, n, l, arr[l]+r);
    
   }
   else if(!strcmp(opt,"Sub"))
   {
    scanf("%d%d",&l,&r);
    updata_tree(arr, tree, 1, 1, n, l, arr[l]-r);  
   }
  }
 }
 return 0;
}

2. I Hate It hdoj1754

本题也是线段树的一个基础用法之一,单点修改,区间查询

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <cmath>
#define int long long
#define Mod 1000000007
#define pi (acos(-1))
#define INF 0x3f3f3f3f3f
#define Maxn 200005
using namespace std;
void build_tree(int arr[], int tree[], int node, int start, int end){
 if( start == end )
 {
  tree[node]=arr[start];
 }
 else
 { 
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  build_tree(arr, tree, left_node , start, mid);
  build_tree(arr, tree, right_node, mid+1, end);
  tree[node]=max(tree[left_node],tree[right_node]);
 } 
} 
void updata_tree(int arr[], int tree[], int node, int start, int end, int loc, int val){
 if( start == end ){
  arr[loc]=val;
  tree[node]=val;
 }
 else
 {
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  if( loc >= start && loc <= mid)
   updata_tree(arr, tree, left_node , start, mid, loc, val);
  else
   updata_tree(arr, tree, right_node, mid+1, end, loc, val);
  tree[node]=max(tree[left_node],tree[right_node]);
 }
}
int max_tree(int arr[], int tree[], int node, int start, int end, int L, int R){
 
 if( R < start || L > end )
  return 0;
 else if( start >= L && end <= R )
  return tree[node];
 else if( start == end )
  return tree[start];
 else{
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  int sum_left  = max_tree(arr, tree, left_node , start, mid, L, R);
  int sum_right = max_tree(arr, tree, right_node, mid+1, end, L, R);
  return max(sum_left,sum_right);
 }
}
signed main(){
 int n,m;
 while(~scanf("%lld%lld",&n,&m)){
  char opt;
  int arr[Maxn]={0};
  for(int i = 1 ; i <= n ; i ++ )
  scanf("%lld",&arr[i]);
  int tree[4*Maxn]={0};
  //建树 
  build_tree(arr,tree,1,1,n);
  for(int i = 0 ; i < m ; i ++ ){
   getchar();
   scanf("%c",&opt);
   int l,r;
   if( opt == 'Q' ){ 
    scanf("%lld%lld",&l,&r);
    printf("%lld\n",max_tree(arr, tree, 1, 1, n, l, r));
   }
   else
   {
    scanf("%lld%lld",&l,&r);
    updata_tree(arr, tree, 1, 1, n, l, r);
   }
  }
 }
 return 0;
}

3.Just a Hook hdoj1698

区间修改,区间查询

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <cmath>
#define int long long
#define Mod 1000000007
#define pi (acos(-1))
#define INF 0x3f3f3f3f3f
#define Maxn 100005
using namespace std;
void PushDown(int add[], int tree[], int node, int start, int end, int L, int R, int val){
 if(add[node]){
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  add[left_node]  = add[node] ;
  add[right_node] = add[node] ;
  tree[left_node]  = add[node] * ( mid - start + 1 );
  tree[right_node] = add[node] * ( end - mid );
  add[node] = 0 ;
 }
}
void build_tree(int arr[], int tree[], int node, int start, int end){
 if( start == end )
 {
  tree[node]=1;
 }
 else
 {
  int left_node  = 2 * node ;
  int right_node = 2 * node + 1 ;
  int mid = ( start + end ) / 2 ;
  build_tree(arr, tree, left_node , start, mid);
  build_tree(arr, tree, right_node, mid+1, end);
  tree[node]=tree[left_node]+tree[right_node];
 }
} 
void updata_tree(int arr[], int tree[], int add[], int node, int start, int end, int L,int R, int val){
 int left_node  = 2 * node ;
 int right_node = 2 * node + 1 ;
 int mid = ( start + end ) / 2 ;
 if( start >= L && end <= R ){
  add[node] = val ;
  tree[node] = val * ( end - start + 1 );
  return ;
 }
 PushDown(add, tree, node, start, end, L, R, val);
 if( L <= mid )
  updata_tree(arr, tree, add, left_node , start, mid, L, R, val);
 if( R > mid )
  updata_tree(arr, tree, add, right_node, mid+1, end, L, R, val);
 tree[node]=tree[left_node]+tree[right_node];
}
signed main(){
 int T;
 scanf("%lld",&T);
 for(int k = 1 ; k <= T ; k ++ ){
  int n;
  scanf("%lld",&n);
  int t;
  scanf("%lld",&t);
  int arr[Maxn]={0};
  for(int i = 1 ; i <= n ; i ++ ) arr[i]=1;
  int tree[4*Maxn]={0};
  int add[4*Maxn]={0};
  //建树 
  build_tree(arr,tree,1,1,n);
//  for(int i = 0 ; i < 30 ; i ++ )
//  printf("tree[%lld] = %lld\n",i,tree[i]);
//  printf("\n");
  while(t--){
   int l,r,z;
   scanf("%lld%lld%lld",&l,&r,&z);
   updata_tree(arr, tree, add, 1, 1, n, l, r, z );
//   for(int i = 0 ; i < 30 ; i ++ )
//  printf("tree[%lld] = %lld\n",i,tree[i]);
//  printf("\n");
  }
  printf("Case %lld: The total value of the hook is %lld.\n",k,tree[1]);
 }
 return 0;
}

4.A Simple Problem with Integers poj3468

区间增减的操作,区间查询

#include <stdio.h>
#include <string.h>
#define Maxn 100002
#define lson start,mid,root << 1
#define rson mid + 1, end, root << 1 | 1
#define int long long
struct Node{
 int lazy, sum;
} tree[Maxn << 2];
void pushUp(int root){
 tree[root].sum = tree[root << 1].sum + tree[root << 1 | 1].sum;
}
void pushDown(int start, int end, int root)
{
 int mid = (start + end) >> 1;
 tree[root << 1].sum += (mid - start + 1) * tree[root].lazy;
 tree[root << 1 | 1].sum += (end - mid) * tree[root].lazy;
 tree[root << 1].lazy += tree[root].lazy;
 tree[root << 1 | 1].lazy += tree[root].lazy;
 tree[root].lazy = 0;
}
void buildTree(int start, int end, int root)
{
 tree[root].lazy = 0;
 if(start == end){
  scanf("%lld", &tree[root].sum);
  return;
 }
 int mid = (start + end) >> 1;
 buildTree(lson); buildTree(rson);
 pushUp(root);
}
void update(int left, int right, int val, int start, int end, int root)
{
 if(left == start && right == end){
  tree[root].sum += (end - start + 1) * val;
  tree[root].lazy += val; return;
 }
 int mid = (start + end) >> 1;
 if(tree[root].lazy) pushDown(start, end, root);
 if(right <= mid) update(left, right, val, lson);
 else if(left > mid) update(left, right, val, rson);
 else {
  update(left, mid, val, lson);
  update(mid + 1, right, val, rson);
 }
 pushUp(root);
}
int query(int left, int right, int start, int end, int root)
{
 if(left == start && right == end) return tree[root].sum;
 int mid = (start + end) >> 1;
 if(tree[root].lazy) pushDown(start, end, root);
 if(right <= mid) return query(left, right, lson);
 else if(left > mid) return query(left, right, rson);
 return query(left, mid, lson) + query(mid + 1, right, rson);
}
signed main()
{
 int n, m, i, a, b;
 char com[2];
 int c;
 while(scanf("%lld%lld", &n, &m) == 2){
  buildTree(1, n, 1);
  while(m--){
   scanf("%s%lld%lld", com, &a, &b);
   if(com[0] == 'Q') 
    printf("%lld\n", query(a, b, 1, n, 1));
   else{
    scanf("%lld", &c);
    update(a, b, c, 1, n, 1);
   }
  }
 }
 return 0;
}

2019牛客暑期多校训练营(第四场)

5.sequence 2019牛客多校第四场C题

还有一点没有搞懂,不知道如何将单调栈和树状数组结合使用,待补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值