BZOJ3211:花神游历各国(线段树)

Description

Input

Output

每次x=1时,每行一个整数,表示这次旅行的开心度

Sample Input

4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4

Sample Output

101
11
11

HINT

对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9

Solution

一个数最多只会被开根$loglog$次(因为每次开根相当于指数除$2$)。

然后用线段树维护一个区间和和区间最大值,如果这个区间的最大值小于等于$1$就没有做的必要了。

去年这个题写了个分块在$BZOJ$被卡了之后就扔着不管了……

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #define N (100009)
 6 #define LL long long
 7 using namespace std;
 8 
 9 struct Sgt{LL max,sum;}Segt[N<<2];
10 int n,m,a[N],opt,x,y;
11 
12 inline int read()
13 {
14     int x=0,w=1; char c=getchar();
15     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
16     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
17     return x*w;
18 }
19 
20 void Build(int now,int l,int r)
21 {
22     if (l==r) {Segt[now].max=a[l]; Segt[now].sum=a[l]; return;}
23     int mid=(l+r)>>1;
24     Build(now<<1,l,mid); Build(now<<1|1,mid+1,r);
25     Segt[now].sum=Segt[now<<1].sum+Segt[now<<1|1].sum;
26     Segt[now].max=max(Segt[now<<1].max,Segt[now<<1|1].max);
27 }
28 
29 void Update(int now,int l,int r,int l1,int r1)
30 {
31     if (Segt[now].max<=1 || l>r1 || r<l1) return;
32     if (l==r) {Segt[now].max=Segt[now].sum=sqrt(Segt[now].sum); return;}
33     int mid=(l+r)>>1;
34     Update(now<<1,l,mid,l1,r1); Update(now<<1|1,mid+1,r,l1,r1);
35     Segt[now].sum=Segt[now<<1].sum+Segt[now<<1|1].sum;
36     Segt[now].max=max(Segt[now<<1].max,Segt[now<<1|1].max);
37 }
38 
39 LL Query(int now,int l,int r,int l1,int r1)
40 {
41     if (l>r1 || r<l1) return 0;
42     if (l1<=l && r<=r1) return Segt[now].sum;
43     int mid=(l+r)>>1;
44     return Query(now<<1,l,mid,l1,r1)+Query(now<<1|1,mid+1,r,l1,r1);
45 }
46 
47 int main()
48 {
49     n=read();
50     for (int i=1; i<=n; ++i) a[i]=read();
51     Build(1,1,n);
52     m=read();
53     while (m--)
54     {
55         opt=read(); x=read(); y=read();
56         if (opt==1) printf("%lld\n",Query(1,1,n,x,y));
57         else Update(1,1,n,x,y);
58     }
59 }

转载于:https://www.cnblogs.com/refun/p/10361888.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值