CF433B
题目简化和分析:
为了更加快速的求出答案,好像没前缀和快速。
为了大家更好的理解线段树,我们使用了线段树。
如果您并不了解线段树,可以转战模板。
因为我们知道线段树可以快速求区间和,于是我们建两棵树。
一个是原来数组,一个是排好序的数组。
每次查询分别用不同的线段树区间和就行了。
Solution:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=4e5+50;
const int M=1e5+50;
inline ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
ll n,m;
ll v[N];
ll ans1[N],ans2[N];
ll ls(ll x){return x<<1;}
ll rs(ll x){return x<<1|1;}
void push_up1(ll p){
ans1[p]=ans1[ls(p)]+ans1[rs(p)];
}
void push_up2(ll p){
ans2[p]=ans2[ls(p)]+ans2[rs(p)];
}
void build1(ll p,ll l,ll r){
if(l==r){ans1[p]=v[l];return;}
ll mid=(l+r)>>1;
build1(ls(p),l,mid);
build1(rs(p),mid+1,r);
push_up1(p);
}
void build2(ll p,ll l,ll r){
if(l==r){ans2[p]=v[l];return;}
ll mid=(l+r)>>1;
build2(ls(p),l,mid);
build2(rs(p),mid+1,r);
push_up2(p);
}
ll query1(ll nx,ll ny,ll l,ll r,ll p){
ll res=0;
if(nx<=l&&r<=ny) return ans1[p];
ll mid=(l+r)>>1;
if(nx<=mid) res+=query1(nx,ny,l,mid,ls(p));
if(ny>mid) res+=query1(nx,ny,mid+1,r,rs(p));
return res;
}
ll query2(ll nx,ll ny,ll l,ll r,ll p){
ll res=0;
if(nx<=l&&r<=ny) return ans2[p];
ll mid=(l+r)>>1;
if(nx<=mid) res+=query2(nx,ny,l,mid,ls(p));
if(ny>mid) res+=query2(nx,ny,mid+1,r,rs(p));
return res;
}
int main()
{
n=read();
for(int i=1;i<=n;++i) v[i]=read();
build1(1,1,n);
sort(v+1,v+n+1);
build2(1,1,n);
m=read();
for(int i=1;i<=m;++i){
ll op,l,r;
op=read();
if(op==1){
l=read(),r=read();
printf("%lld\n",query1(l,r,1,n,1));
}else{
l=read(),r=read();
printf("%lld\n",query2(l,r,1,n,1));
}
}
return 0;
}

浙公网安备 33010602011771号