码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-4027 Can you answer these queries? --线段树

时间:2019-08-17 17:36:53      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:pen   范围   怎么   div   def   names   题意   ase   open   

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4027

题意及思路:

      有一排战舰,给出每个战舰的能力值,存在两种操作:第一种是把一定范围内所有战舰能力值开根号并向下取整,第二种是求一定区域内所有战舰能力值之和。如果我们暴力递归更新区间上的每一个点,会TLE(不要问我是怎么知道的)。我们可以稍微做一些优化。例如能力值0,1。它们开根号还是它们本身,不需要更新。我们可以增加一个标记tag。如果这个区间都是0或者1,我们就把tag标记为1。以后我们再次更新的时候如果区间tag为1,我们就不继续向下递归。

代码:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #define maxn 100000+5
 7 #define LL long long
 8 using namespace std;
 9 typedef struct node
10 {
11     LL a;
12     int tag;
13 }node;
14 node tree[maxn<<2];
15 void pushup(int rt)      //更新节点的和和tag值
16 {
17     tree[rt].a=tree[rt<<1].a+tree[rt<<1|1].a;
18     if(tree[rt<<1].tag&&tree[rt<<1|1].tag)
19         tree[rt].tag=1;
20     return ;
21 }
22 int build(int l,int r,int rt)
23 {
24     if(l==r)
25     {
26         scanf("%lld",&tree[rt].a);
27         if(tree[rt].a==0||tree[rt].a==1)
28             tree[rt].tag=1;
29         return  1;
30     }
31     int m=(l+r)>>1;
32     build(l,m,rt<<1);
33     build(m+1,r,rt<<1|1);
34     pushup(rt);
35 }
36 void update(int L,int R,int l,int r,int rt)
37 {
38     if( L<=l  && r <= R&&tree[rt].tag==1)    //如果区间tag值为1,直接返回
39          return ;
40     if(l==r)
41     {
42         tree[rt].a=(LL)(sqrt(1.0*tree[rt].a));
43         if(tree[rt].a==1||tree[rt].a==0)
44             tree[rt].tag=1;
45         return ;
46     }
47     int m=(l+r)>>1;
48     if(L <= m)
49         update(L,R,l,m,rt<<1);
50     if(R >  m)
51         update(L,R,m+1,r,rt<<1|1);
52     pushup(rt);
53 }
54 LL query(int L,int R,int l,int r,int rt)
55 {
56     if(L <= l && r <= R)
57     {
58         return tree[rt].a;
59     }
60     int m=(l+r)>>1;
61     LL ans=0;
62     if(L <= m)
63         ans+=query(L,R,l,m,rt<<1);
64     if(R > m)
65         ans+=query(L,R,m+1,r,rt<<1|1);
66     return ans;
67 }
68 int main()
69 {
70     int n,jishu;
71     jishu=0;
72     while(scanf("%d",&n)!=EOF)
73     {
74         printf("Case #%d:\n",++jishu);
75         build(1,n,1);
76         int k;
77         scanf("%d",&k);
78         while(k--)
79         {
80             int c,a,b;
81             scanf("%d%d%d",&c,&a,&b);
82             if(a>b)
83                 swap(a,b);
84             if(c==0)
85                 update(a,b,1,n,1);
86             else
87                 cout<<query(a,b,1,n,1)<<endl;
88         }
89         cout<<endl;
90     }
91 }

 

HDU-4027 Can you answer these queries? --线段树

标签:pen   范围   怎么   div   def   names   题意   ase   open   

原文地址:https://www.cnblogs.com/blame/p/11369474.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!