不吸氧是AC,但是为什么我吸氧了后反而全TLE了?
不吸氧 吸氧
确保用的都是相同的一段代码:
提交使用的代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll tree[2000005],a[500005],n,m,op,l,r,x,lz_tag[2000005];
ll ls(ll n){return n*2;}//计算左子树的下标
ll rs(ll n){return n*2+1;}//计算右子树的下标
void pushup(ll n){tree[n]=tree[ls(n)]+tree[rs(n)];}//从下向上传递区间值
void build(ll n,ll nl,ll nr)//建树,n为节点编号,n所指代的区间为[nl,nr]
{
if(nl==nr)//如果到了叶节点
{
tree[n]=a[nl];//把tree[n]赋值为a[nl](因为此时nl==nr而tree[n]=a[nl,nr]区间的加和,所以tree[n]=a[nl])
return;
}
ll mid=(nl+nr)/2;//分治法
build(ls(n),nl,mid);//递归左子树
build(rs(n),mid+1,nr);//递归右子树
pushup(n);//更新值
}
void addtag(ll n,ll nl,ll nr,ll tg)//给节点n打上lazy-tag,并更新
{
lz_tag[n]+=tg;//打上lazy-tag
tree[n]+=tg*(nr-nl+1);//更新
}
void pushdown(ll n,ll nl,ll nr)//区间不能覆盖时,把lazy-tag传给子树
{
if(lz_tag[n])//如果节点n有被标记
{
ll mid=(nl+nr)/2;
addtag(ls(n),nl,mid,lz_tag[n]);//tag传给左子树
addtag(rs(n),mid+1,nr,lz_tag[n]);//tag传给右子树
lz_tag[n]=0;//tag被传走了,将节点n的tag设为0
}
}
ll update(ll l,ll r,ll n,ll nl,ll nr,ll x)//区间修改,把a[l,r]内的每一个元素都加x
{
if(l<=nl&&nr<=r)//如果节点n所指代的区间a[nl,nr]被区间a[l,r]覆盖到了
{
addtag(n,nl,nr,x);//给节点n打上tag
return 0;
}
pushdown(n,nl,nr);//不能覆盖的话,就把tag传给子树们
ll mid=(nl+nr)/2;
if(l<=mid)update(l,r,ls(n),nl,mid,x);//递归左子树
if(r>mid)update(l,r,rs(n),mid+1,nr,x);//递归右子树
pushup(n);//更新
}
ll query(ll l,ll r,ll n,ll nl,ll nr)//查询区间a[l,r]内所有元素的和,n为当前结点的编号,所指代的区间为a[nl,nr]
{
if(l<=nl&&nr<=r)return tree[n];//如果节点n所指代的区间a[nl,nr]被区间a[l,r]覆盖到了
pushdown(n,nl,nr);//不能覆盖的话,就把tag传给子树们
ll mid=(nl+nr)/2,res=0;
if(l<=mid)res+=query(l,r,ls(n),nl,mid);//递归左子树
if(r>mid)res+=query(l,r,rs(n),mid+1,nr);//递归右子树
return res;//返回区间a[l,r]内所有元素的和
}
int main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
build(1,1,n);//建树
for(int i=0;i<m;i++)
{
scanf("%lld",&op);
switch(op)
{
case 1://区间修改,把a[l,r]内的每一个元素都加x
{
scanf("%lld%lld%lld",&l,&r,&x);
update(l,r,1,1,n,x);
break;
}
case 2://区间查询,查询区间a[l,r]内所有元素的和
{
scanf("%lld",&l);
printf("%lld\n",query(l,l,1,1,n));
break;
}
}
}
return 0;
}
懒,就用前几天写的线段数模板写了