版权声明:转载无所谓的。。。 https://blog.csdn.net/xuxiayang/article/details/82809661
链接
https://www.luogu.org/problemnew/show/P3372
大意
给定一个序列,要求支持区间修改和区间查询
思路
线段树啊。。。
(然而跑得比分块还慢。。。)
于是就码了个分块
然后https://www.luogu.org/recordnew/lists?uid=52915&pid=P3372
最后才发现++t放出来就A了!
就A了!
就A了!
就A了!!!!
线段树代码
#include<cstdio>
#include<iostream>
#define lson (k<<1)
#define rson (k<<1|1)
#define mid ((a+b)>>1)
#define LL long long
#define IL inline
using namespace std;
struct node
{
LL l,r,num,lazy;
}tree[400001];//线段树数组
LL n,c[100001],ans,m,x,y,z,k,L=1;
LL slazy(LL k){return (tree[k].r-tree[k].l+1)*tree[k].lazy;}//计算lazy值
IL LL read()//读入优化
{
int d=1;LL f=0;char c;
while(c=getchar(),c<=47||c>=58) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
IL void write(LL x)//输出优化
{
if(x<0) {x=-x;putchar('-');}
if(x>9) write(x/10);putchar(x%10+48);
return;
}
void build2()//非递归构造法(较快)
{
while(L<n) L<<=1;
for(LL i = 1; i <= n; i++)
tree[i+L-1].l=tree[i+L-1].r=i,tree[i+L-1].num=c[i];
for(LL i=L+n;i<L<<1;i++)
tree[i].l=tree[i].r=i-L+1;
for(LL i=L-1;i>=1;i--)
tree[i].l=tree[i<<1].l,
tree[i].r=tree[i<<1|1].r,
tree[i].num+=tree[i<<1].num+tree[i<<1].num;
}
void build(LL k,LL a,LL b)//递归构造法(较慢)注意这里没有处理num
{
tree[k].l=a;
tree[k].r=b;
if(a==b) return;
build(lson,a,mid);build(rson,mid+1,b);
}
IL LL add(LL k)//构造num
{
if(tree[k].l==tree[k].r) return tree[k].num=c[tree[k].r];
return tree[k].num=add(lson)+add(rson);
}
IL void push(LL k)//下传lazy标记
{
if(!tree[k].lazy) return;
tree[lson].lazy+=tree[k].lazy;
tree[rson].lazy+=tree[k].lazy;
tree[k].num+=slazy(k);
tree[k].lazy=0;
}
IL void updata(LL k,LL a,LL b,LL x)//区间修改
{
if(tree[k].l==a&&tree[k].r==b)
{
tree[k].lazy+=x;
return;
}
push(k);//记得下传
if(tree[lson].r>=b) updata(lson,a,b,x);else
if(tree[rson].l<=a) updata(rson,a,b,x);else
{
updata(lson,a,tree[lson].r,x);
updata(rson,tree[rson].l,b,x);
}
tree[k].num=tree[lson].num+tree[rson].num+slazy(lson)+slazy(rson);//维护
}
IL LL find(LL k,LL a,LL b)
{
if(tree[k].l==a&&tree[k].r==b)
return tree[k].num+slazy(k);//到达则返回
push(k);//下传
if(tree[lson].r>=b) return find(lson,a,b);else
if(tree[rson].l<=a) return find(rson,a,b);else
return find(lson,a,tree[lson].r)+find(rson,tree[rson].l,b);//分情况讨论
}
signed main()
{
n=read();m=read();
for(int i=1;i<=n;i++) c[i]=read();//输入
build(1,1,n);
add(1);//这两行可以合起来即为build2
while(m--)
{
k=read();
if(k==1)
{
x=read();y=read();z=read();
updata(1,x,y,z);
}
else
{
x=read();y=read();
write(find(1,x,y));putchar(10);
}
}
}
分块代码
#include<cstdio>
#include<iostream>
#include<cmath>
#define IL inline
#define LL long long
#define r(i,a,b) for(register int i=a;i<=b;i++)
#define N 100010
using namespace std;
LL a[N],sum[N],add[N],ans;
LL L[N],R[N],Pos[N],n,m,x,y,z;
int t;
char c;
IL void change(LL l,LL r,LL d)//区间修改
{
LL p=Pos[l],q=Pos[r];
if(p==q) {r(i,l,r) a[i]+=d,sum[p]+=d;return;}
r(i,p+1,q-1) add[i]+=d;
r(i,l,R[p]) a[i]+=d,sum[p]+=d;
r(i,L[q],r) a[i]+=d,sum[q]+=d;
return;
}
IL LL ask(LL l,LL r)//区间查询
{
LL p=Pos[l],q=Pos[r];
LL ans=0;
if(p==q)//在同一块内
{
r(i,l,r) ans+=a[i]+add[p];
}
else//否则
{
r(i,p+1,q-1) ans+=sum[i]+add[i]*(R[i]-L[i]+1);
r(i,l,R[p]) ans+=a[i]+add[p];
r(i,L[q],r) ans+=a[i]+add[q];
}
return ans;
}
IL LL read()//输入优化
{
int d=1;LL f=0;char c;
while(c=getchar(),c<=47||c>=58) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
IL void write(LL x)//输出优化
{
if(x<0) {x=-x;putchar('-');}
if(x>9) write(x/10);putchar(x%10+48);
return;
}
signed main()
{
n=read();m=read();
r(i,1,n) a[i]=read();
t=(int)sqrt((double)n);
r(i,1,t) L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n;//超级坑点
r(i,1,t) r(j,L[i],R[i]) Pos[j]=i,sum[i]+=a[j];
while(m--)
{
while(c=getchar(),c!='2'&&c!='1');
if(c=='2')
{
x=read();y=read();
ans=ask(x,y);
write(ans);
putchar(10);
}
else
{
x=read();y=read();z=read();
change(x,y,z);
}
}
return 0;
}