题目描述

原题来自:BZOJ 3211

花神喜欢步行游历各国,顺便虐爆各地竞赛。花神有一条游览路线,它是线型的,也就是说,所有游历国家呈一条线的形状排列,花神对每个国家都有一个喜欢程度(当然花神并不一定喜欢所有国家)。

每一次旅行中,花神会选择一条旅游路线,它在那一串国家中是连续的一段,这次旅行带来的开心值是这些国家的喜欢度的总和,当然花神对这些国家的喜欢程序并不是恒定的,有时会突然对某些国家产生反感,使他对这些国家的喜欢度 δ\deltaδ 变为 δ\sqrt \deltaδ​​(可能是花神虐爆了那些国家的 OI,从而感到乏味)。

现在给出花神每次的旅行路线,以及开心度的变化,请求出花神每次旅行的开心值。

输入格式

第一行是一个整数 NNN,表示有 NNN 个国家;

第二行有 NNN 个空格隔开的整数,表示每个国家的初始喜欢度 δi\delta_iδi​​;

第三行是一个整数 MMM,表示有 MMM 条信息要处理;

第四行到最后,每行三个整数 x,l,rx,l,rx,l,r,当 x=1x=1x=1 时询问游历国家 lll 到 rrr 的开心值总和,也就是 ∑i=lrδi\sum\limits_{i=l}^r \delta_ii=lr​​δi​​ ,当 x=2x=2x=2 时国家 lll 到 rrr 中每个国家的喜欢度 δi\delta_iδi​​ 变为 δi\sqrt {\delta_i}δi​​​​ 。

输出格式

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

样例

样例输入

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

样例输出

101
11
11

数据范围与提示

对于全部数据,1≤n≤105,1≤m≤2×105,1≤l≤r≤n,0≤δi≤1091\le n\le 10^5,1\le m\le 2\times 10^5,1\le l\le r\le n,0\le \delta_i \le 10^91n105​​,1m2×105​​,1lrn,0δi​​109​​。

注:建议使用 sqrt 函数,且向下取整。

 

 

开个ma[]维护最大值,如果为1或0,那么就不用修改了(我被100000个0卡了个点。。。这个0很重要!!!)

用sum[]维护区间和

自顶向下不过7次,每次更改维护至叶子结点。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll res=0;
    char ch=0;
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
    return res;
}
int n,m;
ll a[100001],sum[400001],ma[400001];
void build(int k,int l,int r)
{
    if(l==r){sum[k]=ma[k]=a[l];return;}
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    sum[k]=sum[k<<1]+sum[k<<1|1];
    ma[k]=max(ma[k<<1],ma[k<<1|1]);
}
void modify(int k,int l,int r,int x,int y)
{
    if(ma[k]==1||ma[k]==0)return;
    if(l==r){ma[k]=sum[k]=sqrt(sum[k]);return;}
    int mid=l+r>>1;
    if(x<=mid)modify(k<<1,l,mid,x,y);
    if(y>mid)modify(k<<1|1,mid+1,r,x,y);
    sum[k]=sum[k<<1]+sum[k<<1|1];
    ma[k]=max(ma[k<<1],ma[k<<1|1]);
}
ll query(int k,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)return sum[k];
    int mid=l+r>>1;
    ll res=0;
    if(x<=mid)res+=query(k<<1,l,mid,x,y);
    if(y>mid)res+=query(k<<1|1,mid+1,r,x,y);
    return res;
}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)a[i]=read();
    build(1,1,n);
    m=read();
    while(m--)
    {
        int x=read(),y=read(),z=read();
        if(x==1)printf("%lld\n",query(1,1,n,y,z));
        else modify(1,1,n,y,z);
    }
    return 0;
}