题目大意:
就是给定一段区间令其中的数增加一个递增序列(也就是说第一个+1,第二个+2.。。。。)
询问操作是区间的和
这里的查询很简单,但是对于添加递增序列入区间就比较搞脑子了
我们需要一个add[]作为区间的首个数字增加的值,del[]表示等差数列的公差,因为你每次添加进入一个等差数列,是可以叠加的但公差变为了del[ls]+=del[o]
这里主要是pushdown函数的写法
我们要用到等差公式的求和:S =a*n+n(n-1)*d/2
void push_down(int o,int x,int y)
{
int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
if(add[o]||del[o]){
int t1=mid-x+1,t2=y-mid;
LL a2=add[o]+t1*del[o];
sum[ls]+=add[o]*t1+t1*(t1-1)*del[o]/2;
sum[rs]+=a2*t2+t2*(t2-1)*del[o]/2;
add[ls]+=add[o],add[rs]+=a2;
del[ls]+=del[o],del[rs]+=del[o];
add[o]=del[o]=0;
}
}
总代码如下所示:
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define L ls,x,mid 5 #define R rs,mid+1,y 6 #define LL long long 7 #define N 100010 8 LL sum[N<<2],add[N<<2]; 9 int del[N<<2]; 10 void push_up(int o) 11 { 12 sum[o]=sum[o<<1]+sum[o<<1|1]; 13 } 14 void push_down(int o,int x,int y) 15 { 16 int mid=(x+y)/2,ls=o<<1,rs=o<<1|1; 17 if(add[o]||del[o]){ 18 int t1=mid-x+1,t2=y-mid; 19 LL a2=add[o]+t1*del[o]; 20 sum[ls]+=add[o]*t1+t1*(t1-1)*del[o]/2; 21 sum[rs]+=a2*t2+t2*(t2-1)*del[o]/2; 22 add[ls]+=add[o],add[rs]+=a2; 23 del[ls]+=del[o],del[rs]+=del[o]; 24 add[o]=del[o]=0; 25 } 26 } 27 void build(int o,int x,int y) 28 { 29 int mid=(x+y)/2,ls=o<<1,rs=o<<1|1; 30 sum[o]=del[o]=add[o]=0; 31 if(x==y) return; 32 build(L); 33 build(R); 34 } 35 void update(int o,int x,int y,int s,int t) 36 { 37 int mid=(x+y)/2,ls=o<<1,rs=o<<1|1; 38 if(x>=s&&y<=t){ 39 add[o]+=x-s+1; 40 sum[o]+=(x-s+1)*(y-x+1)+(y-x+1)*(y-x)/2; 41 del[o]++; 42 return; 43 } 44 push_down(o,x,y); 45 if(mid>=s) update(L,s,t); 46 if(mid<t) update(R,s,t); 47 push_up(o); 48 } 49 void query(int o,int x,int y,int s,int t,LL &ans) 50 { 51 int mid=(x+y)/2,ls=o<<1,rs=o<<1|1; 52 if(x>=s&&y<=t){ 53 ans+=sum[o]; 54 return; 55 } 56 push_down(o,x,y); 57 if(mid>=s) query(L,s,t,ans); 58 if(mid<t) query(R,s,t,ans); 59 } 60 int main() 61 { 62 int n,q,op,a,b; 63 scanf("%d%d",&n,&q); 64 build(1,1,n); 65 for(int i=0;i<q;i++){ 66 scanf("%d%d%d",&op,&a,&b); 67 if(op){ 68 LL ans=0; 69 query(1,1,n,a,b,ans); 70 printf("%lld\n",ans); 71 } 72 else update(1,1,n,a,b); 73 } 74 return 0; 75 }
SPOJ DCEPC11I
时间: 2024-10-12 21:42:04