第六周周任务——线段树的运用
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题
还有一点没有搞懂,不知道如何将单调栈和树状数组结合使用,待补