题目链接在这里
题目描述:
在[1, n]区间有金属棍,棍的材料有三种,每种有不同的价值。
现在有q种操作,每种操作有x y z三个数,意思是[ x, y ]区间上的金属棍的价值置为z。求q次更新之后,整个区间的总价值是多少。
思路分析:
这是个区间更新操作,如果用暴力更新的方法肯定会超时,所以考虑用线段树。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#define rep(i, n) for(int i = 0; i < n; ++i)
#define clr(x) memset(x, 0, sizeof(x))
#define rl (rt << 1)
#define rr (rt << 1 | 1)
#define llen (tree[rl].r - tree[rl].l + 1)
#define rlen (tree[rr].r - tree[rr].l + 1)
using namespace std;
const int MaxN = 100010;
struct Node{
int l, r, mid;
int mark, sum;
}tree[MaxN << 2];
int n, q, t;
long long ans = 0;
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].mid = (l + r) >> 1;
tree[rt].mark = 0;
if(l == r){
tree[rt].sum = 1;
return;
}
build(l, tree[rt].mid, rl);
build(tree[rt].mid + 1, r, rr);
tree[rt].sum = tree[rl].sum + tree[rr].sum;
}
void pushdown(int rt){
if(tree[rt].mark){
tree[rl].mark = tree[rr].mark = tree[rt].mark;
tree[rl].sum = tree[rl].mark * llen;
tree[rr].sum = tree[rr].mark * rlen;
tree[rt].mark = 0;
}
}
void update(int l, int r, int rt, int w){
if(tree[rt].l == l && tree[rt].r == r){
tree[rt].mark = w;
tree[rt].sum = w * (r - l + 1);
return;
}
pushdown(rt);
if(tree[rt].mid >= r)
update(l, r, rl, w);
else if(tree[rt].mid < l)
update(l, r, rr, w);
else{
update(l, tree[rt].mid, rl, w);
update(tree[rt].mid + 1, r, rr, w);
}
tree[rt].sum = tree[rl].sum + tree[rr].sum;
}
void query(int l, int r, int rt){
if(l == tree[rt].l && r == tree[rt].r){
ans += tree[rt].sum;
return;
}
pushdown(rt);
if(l <= tree[rt].mid) query(l, tree[rt].mid, rl);
if(r > tree[rt].mid) query(tree[rt].mid + 1, r, rr);
}
int main(){
scanf("%d", &t);
int C = 1;
while(t--){
ans = 0;
scanf("%d %d", &n, &q);
build(1, n, 1);
int x, y, z;
while(q--){
scanf("%d %d %d", &x, &y, &z);
update(x, y, 1, z);
}
query(1, n, 1);
printf("Case %d: The total value of the hook is %lld.\n", C++, ans);
}
return 0;
}