时间限制: 1000 ms 内存限制: 524288 KB
提交数: 2830 通过数: 926
【题目描述】
原题来自:BZOJ 3211
花神喜欢步行游历各国,顺便虐爆各地竞赛。花神有一条游览路线,它是线型的,也就是说,所有游历国家呈一条线的形状排列,花神对每个国家都有一个喜欢程度(当然花神并不一定喜欢所有国家)。
每一次旅行中,花神会选择一条旅游路线,它在那一串国家中是连续的一段,这次旅行带来的开心值是这些国家的喜欢度的总和,当然花神对这些国家的喜欢程序并不是恒定的,有时会突然对某些国家产生反感,使他对这些国家的喜欢度 δδ 变为 δ√δ(可能是花神虐爆了那些国家的 OI,从而感到乏味)。
现在给出花神每次的旅行路线,以及开心度的变化,请求出花神每次旅行的开心值。
【输入】
第一行是一个整数 N�,表示有 N� 个国家;
第二行有 N� 个空格隔开的整数,表示每个国家的初始喜欢度 δiδ� ;
第三行是一个整数 M�,表示有 M� 条信息要处理;
第四行到最后,每行三个整数 x,l,r�,�,�,当 x=1�=1 时询问游历国家 l� 到 r� 的开心值总和,就是 ∑ri=lδi∑�=��δ� ,当 x=2�=2 时国家 l� 到 r� 中每个国家的喜欢度 δiδ�变为 δi−−√δ� 。
【输出】
每次 x=1�=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≤�≤105,1≤�≤2×105,1≤�≤�≤�,0≤δ�≤109 。
注:建议使用 sqrt���� 函数,且向下取整。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
ll sum[maxn*4],ma[maxn*4],num[maxn];
void build(int l,int r,int root){
if(l==r){
sum[root]=ma[root]=num[l];return;
}
int m=l+r>>1;
build(l,m,root<<1);
build(m+1,r,root<<1|1);
sum[root]=sum[root<<1]+sum[root<<1|1];
ma[root]=max(sum[root<<1],sum[root<<1|1]);
}
void update(int ul,int ur,int l,int r,int root){
if(ma[root]==1||ma[root]==0) return;
if(l==r){ma[root]=sum[root]=sqrt(sum[root]);return;}
int m=l+r>>1;
if(ul<=m) update(ul,ur,l,m,root<<1);
if(m<ur) update(ul,ur,m+1,r,root<<1|1);
sum[root]=sum[root<<1]+sum[root<<1|1];
ma[root]=max(ma[root<<1],ma[root<<1|1]);
}
ll query(int ql,int qr,int l,int r,int root){
if(ql<=l&&r<=qr) return sum[root];
int m=l+r>>1;
ll ans=0;
if(ql<=m) ans+=query(ql,qr,l,m,root<<1);
if(m<qr) ans+=query(ql,qr,m+1,r,root<<1|1);
return ans;
}
int main()
{
ll n,m;scanf("%lld",&n);
for( int i=1; i<=n; i++ ) scanf("%lld",&num[i]);
build(1,n,1);
scanf("%lld",&m);
for( int i=0; i<m; i++ ){
ll op,a,b;scanf("%lld %lld %lld",&op,&a,&b);
if(op==1) printf("%lld\n",query(a,b,1,n,1));
else update(a,b,1,n,1);
}
return 0;
}
请给个关注和赞赞吧~~~球球了