标签:
Description
Input
Output
Sample Input
Sample Output
解题思路:
线段树更新。因为数据范围的问题,每次更新到节点会TLE。用区间更新就会节省很多的时间,对每一个区间来讲,如果这个区间里面的棍子都是相同类型的,就用一个节点变量记录棍子类型,如果区间内棍子是不同类型,则将变量记录为-1。
#include<iostream> #include<cstdio> using namespace std; #define N 100005 struct node { int l, r, sum; }tree[4*N]; void Build(int root, int l, int r) { tree[root].l = l; tree[root].r = r; tree[root].sum = 1; // 最开始sum都是1,即最开始都是铜金属 if(l == r) return ; Build(2*root+1, l, (l+r)/2); Build(2*root+2, (l+r)/2+1, r); } void inset(int root, int l, int r, int c) { if(tree[root].l == l && tree[root].r == r) { tree[root].sum = c; return ; } if(tree[root].sum != -1) // 如果root这棵树上,左右两个子树上的金属状态一样,但是在这颗树上有要更新的数,所以这个树上的状态就不一样了,就把tree【root】置为-1,把该树的金属状态传下去 { tree[root*2+1].sum = tree[root*2+2].sum = tree[root].sum; tree[root].sum = -1; } int mid = (tree[root].l+tree[root].r)/2; if(r <= mid) inset(2*root+1, l, r, c); else if(l > mid) inset(2*root+2, l, r, c); else { inset(2*root+1, l, mid, c); inset(2*root+2, mid+1, r, c); } } int query(int root, int l, int r) { if(tree[root].sum != -1) // 如果root这个树上的左右两个树上的金属状态一样就直接return树上的数的总和 return tree[root].sum*(r-l+1); int mid = (tree[root].l+tree[root].r)/2; return query(2*root+1, l, mid)+query(2*root+2, mid+1, r); } int main() { int t, q, n, a, b, c; scanf("%d", &t); for(int k = 1; k <= t; k++) { scanf("%d", &n); Build(0, 1, n); scanf("%d", &q); for(int i = 0; i < q; i++) { scanf("%d%d%d", &a, &b, &c); inset(0, a, b, c); } printf("Case %d: The total value of the hook is %d.\n", k, query(0, 1, n)); } return 0; }
http://www.cnblogs.com/alihenaixiao/p/4616575.html
标签:
原文地址:http://www.cnblogs.com/Tinamei/p/4695657.html