// POJ 34681 ≤ N,Q ≤ 100000
// -1000000000 ≤ Ai ≤ 1000000000.
// -10000 ≤ c ≤ 10000.
题目大意:给定 N 个数 ,按照 1 至 N 编号排列。两种操作:
(1) Q i j :查询i 至 j 号的和;
(2) C i j z :成段更新 i 号 到 j 号的值,每个数字都加上 z;
Sample Input
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
Sample Output
4
55
9
15
以下代码 TLE 了,未优化
Result:
Time Limit Exceeded
#include <iostream>
#include <cstdio>
#define Max 100005
using namespace std;
long long sum[Max<<2];
long long val[Max];
int N,Q;
int build(int l,int r,int id)
{if(l==r) { return sum[id]=val[l]; }
int mid=(l+r)/2;
return sum[id]=build(l,mid,id*2)+build(mid+1,r,id*2+1);
}
void update(int x,int L,int R,int l,int r,int id)
{if(l==r) { sum[id]+=x*(r-l+1); return; }
int mid=(l+r)/2;
if(R<=mid)
{ sum[id]+=(R-L+1)*x; update(x,L,R,l,mid,id*2); return; }
else if(L>mid)
{ sum[id]+=(R-L+1)*x; update(x,L,R,mid+1,r,id*2+1); return; }
else
{ sum[id]+=(R-L+1)*x;
update(x,L,mid,l,mid,id*2);
update(x,mid+1,R,mid+1,r,id*2+1);
return;
}
return;
}
int query(int L,int R,int l,int r,int id)
{if(L<=l&&R>=r) { return sum[id]; }
int sums=0;
int mid=(l+r)/2;
if(R<=mid) { sums+=query(L,R,l,mid,id*2); }
else if(L>mid) { sums+=query(L,R,mid+1,r,id*2+1); }
else
{ sums+=query(L,mid,l,mid,id*2)+query(mid+1,R,mid+1,r,id*2+1);}
return sums;
}
int main()
{ //freopen("in.txt","r",stdin);
while(scanf("%d%d",&N,&Q)!=EOF)
{ for(int i=1;i<=N;i++)
scanf("%d",&val[i]);
build(1,N,1);
char com[2]; int a,b,z;
while(Q--)
{ scanf("%s",com);
if(com[0]=='Q')
{ scanf("%d%d",&a,&b);
printf("%d\n",query(a,b,1,N,1));
}
else
{ scanf("%d%d%d",&a,&b,&z); update(z,a,b,1,N,1); }
}
}
return 0;
}
需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新时不要更新到第,用延迟标记似的更新延迟到下次需要更新或者询问到的时候。
AC 代码:
#include <iostream>
#include <cstdio>
#define Max 100005
#define LL long long
using namespace std;
LL sum[Max<<2]; LL add[Max<<2];
int N,Q;
void PushUp(int id)
{sum[id]=sum[id<<1]+sum[id<<1|1]; }
void PushDown(int id,int m)
{if(add[id])
{ add[id*2]+=add[id]; add[id*2+1]+=add[id];
sum[id*2]+=add[id]*(m-m/2); sum[id*2+1]+=add[id]*(m/2);
add[id]=0;
}
return;
}
void build(int l,int r,int id)
{add[id]=0;
if(l==r) { scanf("%lld",&sum[id]); return; }
int mid=(l+r)/2;
build(l,mid,id*2); build(mid+1,r,id*2+1);
PushUp(id);
}
void update(int x,int L,int R,int l,int r,int id)
{if(L<=l&&R>=r) //如果整段都需要被更新
{ sum[id]+=(LL)x*(r-l+1); add[id]+=x; // return; }
PushDown(id,r-l+1);
int mid=(l+r)/2;
if(L<=mid) { update(x,L,R,l,mid,id*2); }
if(R>mid) { update(x,L,R,mid+1,r,id*2+1); }
PushUp(id);
}
LL query(int L,int R,int l,int r,int id)
{if(L<=l&&R>=r) { return sum[id]; }
PushDown(id,r-l+1);
LL sums=0; int mid=(l+r)/2;
if(L<=mid) { sums+=query(L,R,l,mid,id*2); }
if(R>mid) { sums+=query(L,R,mid+1,r,id*2+1); }
return sums;
}
int main()
{while(scanf("%d%d",&N,&Q)!=EOF)
{ build(1,N,1); char com[2]; int a,b,z;
while(Q--)
{ scanf("%s",com);
if(com[0]=='Q')
{ scanf("%d%d",&a,&b);printf("%lld\n",query(a,b,1,N,1)); }
else
{ scanf("%d%d%d",&a,&b,&z); update(z,a,b,1,N,1); }
}
}
return 0;
}