https://nanti.jisuanke.com/t/31460
这题用线段树和树状数组都能过
大致思路就是维护两个线段树,一个是存每个元素(下标为i)的区间和,另一个存每个元素乘n-i+1的区间和。
询问时只需用第二个线段树的区间和减去第一个线段树的区间和的(n-left)倍数就行了
WA原因:int改成longlong一定要检查一下各函数返回值和scanf中是否也改成了longlong啊。。
线段树版本:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define MAXN 100006
#define inf 0x3f3f3f3f
using namespace std;
typedef unsigned long long ll;
int n,m,t;
struct node1{
int l,r;//区间[l,r]
ll add;//区间的延时标记
ll sum;//区间和
}tree1[MAXN*4];
struct node2{
int l,r;
ll add;
ll sum;
}tree2[MAXN*4];
void pushup1(int index){
tree1[index].sum = tree1[index<<1].sum+tree1[index<<1|1].sum;
}
void pushup2(int index){
tree2[index].sum = tree2[index<<1].sum+tree2[index<<1|1].sum;
}
void pushdown1(int index){
if(tree1[index].add){
tree1[index<<1].sum = (tree1[index<<1].r-tree1[index<<1].l+1)*tree1[index].add;
tree1[index<<1|1].sum = (tree1[index<<1|1].r-tree1[index<<1|1].l+1)*tree1[index].add;
tree1[index<<1].add = tree1[index].add;
tree1[index<<1|1].add = tree1[index].add;
tree1[index].add = 0;
}
}
void pushdown2(int index){
if(tree2[index].add){
tree2[index<<1].sum = (tree2[index<<1].r-tree2[index<<1].l+1)*tree2[index].add;
tree2[index<<1|1].sum = (tree2[index<<1|1].r-tree2[index<<1|1].l+1)*tree2[index].add;
tree2[index<<1].add = tree2[index].add;
tree2[index<<1|1].add = tree2[index].add;
tree2[index].add = 0;
}
}
void build(int l,int r,int index){
tree1[index].l=tree2[index].l=l;
tree1[index].r=tree2[index].r=r;
tree1[index].add=tree2[index].add=0;
if(l==r){
scanf("%lld",&tree2[index].sum);
tree1[index].sum=(n-t)*tree2[index].sum;
//cout<<"&"<<tree1[index].sum<<endl;
t++;
return;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup1(index);
pushup2(index);
}
void updata1(int l,int r,int index,ll val){
if(l <= tree1[index].l && r >= tree1[index].r){
tree1[index].sum = (tree1[index].r-tree1[index].l+1)*val;
tree1[index].add = val;
return ;
}
pushdown1(index);
int mid = (tree1[index].l+tree1[index].r)>>1;
if(l <= mid){
updata1(l,r,index<<1,val);
}
if(r > mid){
updata1(l,r,index<<1|1,val);
}
pushup1(index);
}
void updata2(int l,int r,int index,ll val){
if(l <= tree2[index].l && r >= tree2[index].r){
tree2[index].sum = (tree2[index].r-tree2[index].l+1)*val;
tree2[index].add = val;
return ;
}
pushdown2(index);
int mid = (tree2[index].l+tree2[index].r)>>1;
if(l <= mid){
updata2(l,r,index<<1,val);
}
if(r > mid){
updata2(l,r,index<<1|1,val);
}
pushup2(index);
}
ll query1(int l,int r,int index){
if(l <= tree1[index].l && r >= tree1[index].r){
return tree1[index].sum;
}
//cout<<"&"<<tree1[index].sum<<endl;
pushdown1(index);
int mid=(tree1[index].l+tree1[index].r)>>1;
ll ans=0;
if(l <= mid){
ans += query1(l,r,index<<1);
}
if(r > mid){
ans += query1(l,r,index<<1|1);
}
return ans;
}
ll query2(int l,int r,int index){
if(l <= tree2[index].l && r >= tree2[index].r){
return tree2[index].sum;
}
pushdown2(index);
int mid=(tree2[index].l+tree2[index].r)>>1;
ll ans=0;
if(l <= mid){
ans += query2(l,r,index<<1);
}
if(r > mid){
ans += query2(l,r,index<<1|1);
}
return ans;
}
int main()
{
int q,x,y;
ll z;
while(~scanf("%d%d",&n,&m)){
build(1,n,1);
while(m--){
t=1;
scanf("%d",&q);
if(q == 1){
scanf("%d %d",&x,&y);
ll q1=query1(x,y,1);
ll q2=query2(x,y,1);
if(n==y)
cout<<q1<<endl;
else
cout<<q1-(n-y)*q2<<endl;
}
else{
scanf("%d %lld",&x,&z);
updata1(x,x,1,(n-x+1)*z);
updata2(x,x,1,z);
}
}
}
return 0;
}
树状数组版本:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m;
ll a[N],b[N];
ll lowbit(ll x){
return (-x)&x;
}
void add1(ll pos,ll x){
while(pos<=n){
a[pos]+=x;
pos+=lowbit(pos);
}
}
void add2(ll pos,ll x){
while(pos<=n){
b[pos]+=x;
pos+=lowbit(pos);
}
}
ll query1(ll pos){
ll res=0;
while(pos>0){
res+=a[pos];
pos-=lowbit(pos);
}
return res;
}
ll query2(ll pos){
ll res=0;
while(pos>0){
res+=b[pos];
pos-=lowbit(pos);
}
return res;
}
void input(){
ll x;
for(int i=1;i<=n;i++){
scanf("%lld",&x);
add2(i,x);
add1(i,x*(n-i+1));
}
}
int main(){
scanf("%d%d",&n,&m);
input();
int f;
ll x,y;
for(int i=1;i<=m;i++){
scanf("%d%lld%lld",&f,&x,&y);
if(f==2){
ll pre=query2(x)-query2(x-1);
add2(x,y-pre);
add1(x,(y-pre)*(n-x+1));
}
else if(f==1){
ll s2=query2(y)-query2(x-1);
ll s1=query1(y)-query1(x-1);
cout<<s1-(n-y)*s2<<endl;
}
}
return 0;
}