hdu 4027 线段树 + 带次数的区间内每个点修改

题意:

n个数组成的一个序列,下标从1开始。现在共进行m次区间修改和查询工作。0 l r表示[l , r]内每个数开平方向下取整。

1 l r表示对[l ,r]求和。1 <= n <= 100000 , 1 <= m <= 100000。

题解:

1.乍一看需要对区间内每个点修改,后来发现每个点最多改6~7次,可以用vis标记这个区间已经全部是1无需再进行开方操作

2.接下来就是线段树套路求和了。

#include<bits/stdc++.h>
#define N 100005
using namespace std ;
int n ;
long long a[N << 2] ;
long long sum[N << 2] ;
bool vis[N << 2] ;
void build(int l , int r , int num)
{
    int lson = num * 2 , rson = num * 2 + 1 ;
    int mid = (l + r) / 2 ;
    if(l == r)
    {
        sum[num] = a[l] ;
        return ;
    }
    build(l , mid , lson) ;
    build(mid + 1 , r , rson) ;
    sum[num] = sum[lson] + sum[rson] ;
}
void update(int x , int y , int l , int r , int num)
{
    int lson = num * 2 , rson = num * 2 + 1 ;
    int mid = (l + r) / 2 ;
    if(x > r || y < l || vis[num])
       return ;
    if(l == r)
    {
        sum[num] = (long long)(sqrt(sum[num])) ;
        if(sum[num] <= 1)
           vis[num] = 1 ;
        return ;
    }
    update(x , y , l , mid , lson) ;
    update(x , y , mid + 1 , r , rson) ;
    sum[num] = sum[lson] + sum[rson] ;
    vis[num] = vis[lson] && vis[rson] ;
}
long long query(int x , int y , int l , int r , int num)
{
    int lson = num * 2 , rson = num * 2 + 1 ;
    int mid = (l + r) / 2 ;
    long long ans = 0 ;
    if(x > r || y < l)
       return 0 ;
    if(x <= l && r <= y)
    {
        return sum[num] ;
    }
    ans += query(x , y , l , mid , lson) ;
    ans += query(x , y , mid + 1 , r , rson) ;
    return ans ;
}
int main()
{
    int i , j ;
    int m ;
    int t = 0 ;
    int flag , l , r ;
    while(scanf("%d" , &n) != EOF)
    {
      for(i = 1 ; i <= n ; i ++)
        scanf("%lld" , &a[i]) ;
      memset(vis , 0 , sizeof(vis)) ;
      memset(sum , 0 , sizeof(sum)) ;
      build(1 , n , 1) ;
      scanf("%d" , &m) ;
      printf("Case #%d:\n" , ++t) ;
      while(m --)
      {
          scanf("%d%d%d" , &flag , &l , &r) ;
          if(l > r)
             swap(l , r) ;
          if(flag == 0)
             update(l , r , 1 , n , 1) ;
          else
             printf("%lld\n" , query(l , r , 1 , n , 1)) ;
      }
      printf("\n") ;
    }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值