洛谷 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;
}
相关文章推荐
- 【洛谷3372】 线段树 1
- 洛谷3372[模板]线段树1
- 洛谷 3372_【模板】线段树 1_线段树
- 【Splay】洛谷3372 【模板】线段树 1
- 【模板】线段树 洛谷 3372 线段树
- 洛谷3372 线段树1
- 洛谷P1198 [JSOI2008]最大数(线段树)
- 【洛谷】线段树 树状数组区间修改区间查询
- 二分查找or线段树(借教室洛谷1083vijos1782NOIP 2012 提高组 第二天 第二题)
- 洛谷[P3616] 富金森林公园【数据结构】【线段树】【树状数组】
- AC日记——【模板】线段树 1 洛谷 P3372
- 洛谷3707 [SDOI2017] 相关分析 【线段树】
- 洛谷9月月赛 康娜的线段树
- 【线段树】洛谷 P3372 【模板】线段树 1
- AC日记——【模板】线段树 2 洛谷 P3373
- 洛谷 P3372 【模板】线段树 1
- [hdu&poj&洛谷] 经典线段树练习题
- 洛谷 U14475 部落冲突 【比赛】 【树链剖分 + 线段树】
- 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)
- 洛谷 3373(线段树,区间加减及乘法 询问区间和)