hook有三种stick,分别为1号,2号, 3号,长度分别为1,2,3;T个测试样例, N个stick,Q个操作,每次操作改变x-y区间内stick的值,最后求和;
话不多说,代码奉上:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#define MAX 100000+5
using namespace std;
int arr[MAX]; //储存初始值(对树初始化时存入叶子的值);
struct node{ //结构体储存树的结点;
int left; //该结点的左边界;
int right; //右边界;
int val; //结点的值;此题中是区间和;
int mark; //标记;
}tr[MAX<<2];
void pushup(int node) //维护结点;
{
tr[node].val=tr[node<<1].val+tr[node<<1|1].val;
return;
}
void build(int node, int left, int right) //建线段树,传参:树根, 左边界,右边界;
{
tr[node].left=left; //确定该结点的作用区间;
tr[node].right=right; //同上;
tr[node].mark=0; //把标记初始化为零(此句必须有);
if(tr[node].left==tr[node].right) //该结点为叶结点,初始化叶结点;
{
tr[node].val=arr[left];
return;
}
int mid=(left+right)>>1;
build(node<<1, left, mid);
build(node<<1|1, mid+1, right);
pushup(node);
}
void mark(int node) //判断是否标记;
{
if(tr[node].mark){
tr[node].val=tr[node].mark*(tr[node].right-tr[node].left+1);
if(tr[node].left!=tr[node].right){ //if是叶子则没有下一层可标记,不是叶子就标记下一层;
tr[node<<1].mark=tr[node].mark;
tr[node<<1|1].mark=tr[node].mark;
}
tr[node].mark=0; //消除标记;
}
return;
}
void update(int node, int left, int right, int x)//区间更新;
{
mark(node); //每次更新前先看该层是否有标记,有标记就把标记跑一遍;
if(left>tr[node].right || right<tr[node].left) return;
if(left<=tr[node].left && right>=tr[node].right){
tr[node].val=x*(tr[node].right-tr[node].left+1);
tr[node].mark=x; //标记结点;
return;
}
update(node<<1, left, right, x);
update(node<<1|1, left, right, x);
pushup(node); //维护父结点;
}
int main(){
int T, cnt=0;
scanf("%d",&T);
while(T--){
cnt++;
int N, i;
scanf("%d",&N);
for(i=1; i<=N; i++)
arr[i]=1;
build(1, 1, N);
int Q;
scanf("%d",&Q);
while(Q--){
int a, b, c;
scanf("%d%d%d",&a,&b,&c);
update(1, a, b, c);
}
printf("Case %d: The total value of the hook is %d.\n",cnt,tr[1].val);
}
return 0;
}