Description
Input
Output
Sample Input
Sample Output
思路:
0:代表线段被覆盖了。
1,2,3:分别代表值。
先建立线段树:
【1,10】
1
/ \
【1,5】 【6,10】
1 1
/ \ / \
【1,3】 【4,5】 【6,8】 【9,10】
1 1 1 1
/ \ / \ / \ / \
【1,2】 【3,3】【4,4】【5,5】 【6,7】【8,8】【9,9】【10,10】
1 1 1 1 1 1 1 1
/ \ / \
【1,1】 【2,2】 【6,6】 【7,7】
1 1 1 1
插入1 5 2后:
【1,10】
0
/ \
【1,5】 【6,10】
2 1
/ \ / \
【1,3】 【4,5】 【6,8】 【9,10】
1 1 1 1
/ \ / \ / \ / \
【1,2】 【3,3】【4,4】【5,5】 【6,7】【8,8】【9,9】【10,10】
1 1 1 1 1 1 1 1
/ \ / \
【1,1】 【2,2】 【6,6】 【7,7】
插入5 9 3后:
【1,10】
0
/ \
【1,5】 【6,10】
0 0
/ \ / \
【1,3】 【4,5】 【6,8】 【9,10】
2 0 3 0
/ \ / \ / \ / \
【1,2】 【3,3】【4,4】【5,5】 【6,7】【8,8】【9,9】【10,10】
1 2 3 1 1 3 1
/ \ / \
【1,1】 【2,2】 【6,6】 【7,7】
1 1 1 1
将红色的值加起来就是答案24了。
#include#include using namespace std;const int MAXN = 100001;int n;//hooks的个数int q;//operations的个数struct Node{ int l;//左端点 int r;//右端点 int v;//价值}tree[MAXN * 4];void BuildTree(int t,int l,int r){ tree[t].l = l; tree[t].r = r; tree[t].v = 1; if (l == r)//为叶节点 return ; BuildTree(t + t,l,(l + r) / 2);//建立左子树 BuildTree(t + t + 1,(l + r) / 2 + 1,r);//建立右子树}void Update(int t,int l,int r,int v){ if (tree[t].l == l && tree[t].r == r)//区间匹配 { tree[t].v = v;//将value覆盖 return ; } if (tree[t].v == v)//如果值相同,就没必要更改 return ; if (tree[t].v > 0)//区间tree[t].l到tree[t].r的值要更改 { tree[t + t + 1].v = tree[t + t].v = tree[t].v; tree[t].v = 0; } if (r <= (tree[t].l + tree[t].r) / 2)//在左孩子 Update(t + t,l,r,v); else if (l > (tree[t].l + tree[t].r) / 2)//在右孩子 Update(t + t + 1,l,r,v); else//横跨中点 { Update(t + t,l,(tree[t].l + tree[t].r) / 2,v); Update(t + t + 1,(tree[t].l + tree[t].r) / 2 + 1,r,v); }}int GetValue(int t){ int ans = 0; if (tree[t].v > 0) ans += (tree[t].r - tree[t].l + 1) * tree[t].v; else { ans += GetValue(t + t); ans += GetValue(t + t + 1); } return ans;}int main(void){ int t,x,y,z,i = 1; scanf("%d",&t); while (t --) { scanf("%d",&n); BuildTree(1,1,n);//建立线段树 scanf("%d",&q); while (q --) { scanf("%d%d%d",&x,&y,&z); Update(1,x,y,z);//更新区间的值 } printf("Case %d: The total value of the hook is %d.\n",i ++,GetValue(1));//得到value的总值 } return 0;}