您的位置:首页 > 其它

洛谷 3372 【模(mú)板】线段树 1

2018-03-02 23:29 281 查看

首先先讲树状数组的做法,别问我为什么!

同3368一样用差分数组。使差分数组1到x的和为ans(x)。

建立一个新的树状数组ans1(x)=差分(x)*(x-1)

不过那也就是x——y的答案为

(y*ans(y)-(x-1)*ans1(x-1))-(ans(y)-ans1(x-1))

树状数组代码

#include <cstdio>
#include <cctype>
#define ll long long
using namespace std;
ll n,a[500001],b[500001],m;
ll lowbit(ll x){return x&(-x);}
ll in(){
ll ans=0; char c=getchar(); int f=1;
while (!isdigit(c)&&c!='-') c=getchar();
if (c=='-'){f=-f;c=getchar();}
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void add(ll x,ll k){
while (x<=n){
a[x]+=k;
x+=lowbit(x);
}
}
void add1(ll x,ll k){
while (x<=n){
b[x]+=k;
x+=lowbit(x);
}
}
ll sum1(ll x){
ll ans=0;
while (x>0){
ans+=b[x];
x-=lowbit(x);
}
return ans;
}
ll sum(ll x){
ll ans=0;
while (x>0){
ans+=a[x];
x-=lowbit(x);
}
return ans;
}
int main(){
n=in(); m=in();
for (ll i=1,o=0,x;i<=n;i++) x=in(),add(i,x-o),add1(i,(i-1)*(x-o)),o=x;
while (m--){
ll q,l,r,x; q=in();
if (q==1){l=in(); r=in(); x=in(); add(r+1,-x); add(l,x); add1(l,x*(l-1)); add1(r+1,-x*r);}
else {l=in(); r=in(); printf("%lld\n",r*sum(r)-sum1(r)-(l-1)*sum(l-1)+sum1(l-1));}//查找
}
return 0;
}


正题:

线段树

样例输入

5 5

1 5 4 2 3

2 2 4

1 2 3 2

2 3 4

1 1 5 1

2 1 4

样例输出

11

8

20



建造

inline ll build(ll l,ll r,ll k){
if (l==r) return tree[k].w=a[r];
else return tree[k].w=build(l,(l+r)>>1,k<<1)+build(((l+r)>>1)+1,r,(k<<1)+1);
}


添改

void update(ll l,ll r,ll x,ll y,ll res,ll k){
if (x==l&&y==r) {tree[k].w+=res*(r-l+1); tree[k].lazy+=res; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);//左边的lazy标记
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);//右边的lazy标记
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) update(l,mid,x,y,res,k<<1);
else if (x>mid) update(mid+1,r,x,y,res,(k<<1)+1);
else update(l,mid,x,mid,res,k<<1),update(mid+1,r,mid+1,y,res,(k<<1)+1);
tree[k].w=tree[(k<<1)+1].w+tree[k<<1].w;
}


查找

void find(ll l,ll r,ll x,ll y,ll k){
if (x==l&&y==r) {ans+=tree[k].w; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) find(l,mid,x,y,k<<1
f246
);
else if (x>mid) find(mid+1,r,x,y,(k<<1)+1);
else find(l,mid,x,mid,k<<1),find(mid+1,r,mid+1,y,(k<<1)+1);
}


线段树代码

#include <cstdio>
#include <cctype>
#define ll long long
using namespace std;
struct node{
ll w,lazy;
}tree[2000001]; ll n,m,ans,a[500001];
inline ll inp(){
char c=getchar(); ll ans=0,f=1;
while (!isdigit(c)&&c!='-') c=getchar();
if (c=='-') f=-f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void find(ll l,ll r,ll x,ll y,ll k){
if (x==l&&y==r) {ans+=tree[k].w; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) find(l,mid,x,y,k<<1);
else if (x>mid) find(mid+1,r,x,y,(k<<1)+1);
else find(l,mid,x,mid,k<<1),find(mid+1,r,mid+1,y,(k<<1)+1);
}
inline ll build(ll l,ll r,ll k){ if (l==r) return tree[k].w=a[r]; else return tree[k].w=build(l,(l+r)>>1,k<<1)+build(((l+r)>>1)+1,r,(k<<1)+1); }
void update(ll l,ll r,ll x,ll y,ll res,ll k){
if (x==l&&y==r) {tree[k].w+=res*(r-l+1); tree[k].lazy+=res; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) update(l,mid,x,y,res,k<<1);
else if (x>mid) update(mid+1,r,x,y,res,(k<<1)+1);
else update(l,mid,x,mid,res,k<<1),update(mid+1,r,mid+1,y,res,(k<<1)+1);
tree[k].w=tree[(k<<1)+1].w+tree[k<<1].w;
}
inline void in1(ll &x,ll &y){x=inp(); y=inp();}
int main(){
n=inp(); m=inp();
for (ll i=1;i<=n;i++) a[i]=inp();
build(1,n,1);
while (m--){
ll q=inp(),x,y,k;ans=0;
if (q==1) in1(x,y),k=inp(),update(1,n,x,y,k,1);
else in1(x,y),find(1,n,x,y,1),printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: