hdu2823

线段树原来遇到过了,不过自己写还是很容易出现问题,特别是递归的时候总是忘记返回,这样老是会爆栈

还有,好像分析问题的能力很欠缺,而且宏观的概念不是很好,其实感觉写递归就两点,第一宏观上整体把握,第二细节上仔细认真

这道题还是整了我很久,真的不太 清楚别人到底是怎么想出来的,反正我是无能为力了。还是先学习这把,突然让我心里升起了征服的欲望

还是回头继续说这道题把,关于线段树的优点不言而喻了,把整个大区间分成了一个一个的小区间,这道题恰好利用了这个性质,更改的时候整个区间一块更改了

这里的标记兼价值flag很有意思,这样来解释下把,初始化为1,当线段树中的父节点的所有子节点的flag都一样时,父节点的flag为1(2,3),否则为-1,

更改的时候,若父节点的所有子节点的flag一样,则父节点的flag不为-1(可能为1,2,3),否则标记为-1

查询的时候只查询记录那些flag为1的节点,不为1的则没有什么价值

下面贴出代码,刚开死根本update(),和query()根本看不懂,还是debug了一下,然后豁然开朗

 1 #include <stdio.h>
 2 #include <cstring>
 3 int a[100005];
 4 struct node
 5 {
 6     int left;
 7     int right;
 8     int flag;
 9 };
10 node tree[100005*4];
11 int n;
12 int sum;
13 
14 
15 void build (int left,int right,int root)
16 {
17     tree[root].left=left;
18     tree[root].right=right;
19     tree[root].flag=1;//表示在这个区间内的点都是1 level的
20     if(left==right)
21     {
22         return;//这里刚开始忘了return,唉,爆栈了
23     }
24     int mid=(left+right)/2;
25     build(left,mid,root*2);
26     build(mid+1,right,root*2+1);
27 }
28 
29 
30 void update(int left,int right,int root,int level)
31 {
32     if(tree[root].right<left || tree[root].left > right )//完全不在区间内
33     {
34         return ;
35     }
36     if(tree[root].left>=left && tree[root].right<=right)//完全在区间内
37     {
38         tree[root].flag=level;
39         return;
40     }
41     if(tree[root].flag!=-1)//只有一部分在区间内,所以这个范围内的数据时脏的
42     {
43         tree[root*2].flag=tree[root].flag;
44         tree[root*2+1].flag=tree[root].flag;
45         tree[root].flag=-1;//标记这个父节点,表示其子节点中有脏数据
46     }
47     update(left,right,root*2,level);
48     update(left,right,root*2+1,level);
49 }
50 
51 
52 void query(int root)
53 {
54     if(tree[root].flag!=-1)
55     {
56         sum=sum+tree[root].flag*(tree[root].right-tree[root].left+1);
57         return ;//递归的时候一定要注意返回
58     }
59     if(tree[root].left==tree[root].right)//查询到子节点要返回,否则一直递归下去,递归的时候注意什么时候返回,重要
60     {
61         return ;
62     }
63     query(root*2);
64     query(root*2+1);
65 }
66 
67 int main()
68 {
69     int Case,q;
70     int start,end,level;
71     scanf("%d",&Case);
72     int k=1;
73     while(Case--)
74     {
75         scanf("%d%d",&n,&q);
76         build(1,n,1);
77         while(q--)
78         {
79             scanf("%d%d%d",&start,&end,&level);
80             update(start,end,1,level);
81         }
82         sum=0;
83         query(1);
84         printf("Case %d: The total value of the hook is %d.\n",k++,sum);
85     }
86     return 0;
87 }

唉,征服的欲望啊

转载于:https://www.cnblogs.com/devil-91/archive/2012/08/20/2646952.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值