A - A Simple Problem with Integers
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
数据:
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
AC代码:
const int maxn=1e5+5; ll a[maxn],n,m; struct Node{ ll l,r,su; ll lazy; }tree[maxn<<2+5]; void build(ll l,ll r,ll k) { tree[k].su=0; tree[k].lazy=0; tree[k].l=l; tree[k].r=r; if(l==r){ tree[k].su=a[l]; return ; } else{ ll mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); tree[k].su=tree[k<<1].su+tree[k<<1|1].su; } } void down(int k)//k节点lazy标记下传一位 { if(tree[k].l==tree[k].r) { //叶子节点 //tree[k].su+=tree[k].lazy; return ; } tree[k<<1].su+=((tree[k<<1].r-tree[k<<1].l+1)*tree[k].lazy); tree[k<<1].lazy+=tree[k].lazy; tree[k<<1|1].su+=((tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].lazy); tree[k<<1|1].lazy+=tree[k].lazy; tree[k].lazy=0; } void update(ll l,ll r,ll k,ll p)//区间修改 { if(tree[k].l>=l && tree[k].r<=r)//不再往下走,lazy标记 {//lazy表示改点以下的节点还未修改 tree[k].su+=((tree[k].r-tree[k].l+1)*p); tree[k].lazy+=p; return ; } //如果节点区间未被全包含,lazy下传 if(tree[k].lazy) down(k); ll mid=((tree[k].l+tree[k].r)>>1); if(l<=mid) update(l,r,k<<1,p); if(r>mid) update(l,r,k<<1|1,p); tree[k].su=tree[k<<1].su+tree[k<<1|1].su; } ll sum=0;//存区间和 void summ(ll l,ll r,ll k)//区间和 { if(tree[k].l>=l && tree[k].r<=r) { sum+=tree[k].su; return ; } if(tree[k].lazy) down(k); ll mid=((tree[k].l+tree[k].r)>>1); if(l<=mid) summ(l,r,k<<1); if(r>mid) summ(l,r,k<<1|1); } /* void add(ll n,ll x,ll k)//单点修改 { if(tree[k].l<=n && n<=tree[k].r) { tree[k].su+=x; if(!(tree[k].l==tree[k].r)) { ll mid=(tree[k].l+tree[k].r)>>1; add(n,x,k<<1); add(n,x,k<<1|1); } } } */ int main() { scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++) scanf("%lld",a+i); //for(ll i=1;i<=n;i++) scanf("%lld",x),add());//原先代码(超时) build(1,n,1); char s; while(m--) { getchar(); scanf("%c",&s); ll a,b,c; if(s=='Q') { scanf("%lld%lld",&a,&b); sum=0; summ(a,b,1); printf("%lld ",sum); } else{ scanf("%lld%lld%lld",&a,&b,&c); update(a,b,1,c); } } return 0; }
->:一直超时,只要去掉单点修改,在build时就将初始数据加入线段树
还有读数别用cin...
void build(ll l,ll r,ll k) { tree[k].su=0; tree[k].lazy=0; tree[k].l=l; tree[k].r=r; if(l==r){ tree[k].su=a[l];// return ; } else{ ll mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); tree[k].su=tree[k<<1].su+tree[k<<1|1].su;//省去单点修改 } }