题目:线段树 1
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;
#define ll long long
#define maxn 100000
int n,m;
ll a[maxn+5];
ll Sum[4*maxn+5];
int X,Y;
ll add[4*maxn+5]= {0}; //标记
void build_tree(int o,int L,int R) { //建树
if(L==R) { //叶子节点
Sum[o]=a[L];
return ;
}
int lson=o*2,rson=o*2+1;
int mid=(L+R)/2;
build_tree(lson,L,mid),build_tree(rson,mid+1,R);
Sum[o]=Sum[lson]+Sum[rson];
return ;
}
void update(int o,int L,int R,ll v) { //修改
int mid=(L+R)/2;
int lson=2*o,rson=2*o+1;
if(X<=L&&R<=Y) { //边界,即线段被查询的区间完全覆盖
add[o]+=v;
} else {
if(X<=mid) update(lson,L,mid,v);
if(Y>mid) update(rson,mid+1,R,v);
}
if(R>L) Sum[o]=Sum[lson]+Sum[rson]; //有子树
else Sum[o]=a[L]; //叶子结点
Sum[o]+=(R-L+1)*add[o];
}
ll s;
void query(int o,int L,int R,ll Add){ //查询
int mid=(L+R)/2;
int lson=2*o,rson=2*o+1;
if(X<=L&&R<=Y) { //边界
s=s+Sum[o]+(R-L+1)*Add;
return ;
}
if(X<=mid) query(lson,L,mid,Add+add[o]); //将当前节点的标记向下传递
if(Y>mid) query(rson,mid+1,R,Add+add[o]);
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
ll x;
scanf("%lld",&x);
a[i]=x;
}
build_tree(1,1,n);
for(int i=1; i<=m; i++) {
int opr;
scanf("%d",&opr);
if(opr==1) {
ll v;
scanf("%d%d%lld",&X,&Y,&v);
if(X>Y) swap(X,Y);
update(1,1,n,v);
} else {
scanf("%d%d",&X,&Y);
if(X>Y) swap(X,Y);
s=0;
query(1,1,n,0);
printf("%lld\n",s);
}
}
return 0;
}
题目:线段树 2
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;
#define ll long long
#define maxn 100000
ll n,m,P;
ll a[maxn+5]= {0};
ll Sum[4*maxn+5]= {0};
ll X,Y;
ll add[4*maxn+5]= {0};
ll mul[4*maxn+5]= {0};
void build_tree(ll o,ll L,ll R) { //建树
add[o]=0,mul[o]=1;
if(L==R) {
Sum[o]=a[L];
return ;
}
ll lson=o*2,rson=o*2+1;
ll mid=(L+R)/2;
build_tree(lson,L,mid),build_tree(rson,mid+1,R);
Sum[o]=(Sum[lson]+Sum[rson])%P;
return ;
}
void push_down(ll o,ll lson,ll rson,ll L,ll R) { //下移标记
if(!add[o]&&mul[o]==1) return ;
ll mid=(L+R)/2;
mul[lson]=mul[lson]*mul[o]%P;
mul[rson]=mul[rson]*mul[o]%P;
add[lson]=(add[lson]*mul[o]+add[o])%P;
add[rson]=(add[rson]*mul[o]+add[o])%P;
Sum[lson]=(Sum[lson]*mul[o]+add[o]*(mid-L+1))%P;
Sum[rson]=(Sum[rson]*mul[o]+add[o]*(R-mid))%P;
mul[o]=1,add[o]=0;
return ;
}
void update_add(ll o,ll L,ll R,ll v) { //加法
ll mid=(L+R)/2;
ll lson=2*o,rson=2*o+1;
if(X<=L&&R<=Y) {
add[o]=(add[o]+v)%P;
Sum[o]=(Sum[o]+(R-L+1)*v)%P;
} else {
push_down(o,lson,rson,L,R);
if(X<=mid) update_add(lson,L,mid,v);
if(Y>mid) update_add(rson,mid+1,R,v);
Sum[o]=(Sum[lson]+Sum[rson])%P;
}
}
void update_mul(ll o,ll L,ll R,ll v) { //乘法
ll mid=(L+R)/2;
ll lson=2*o,rson=2*o+1;
if(X<=L&&R<=Y) {
mul[o]=mul[o]*v%P;
add[o]=add[o]*v%P;
Sum[o]=Sum[o]*v%P;
} else {
push_down(o,lson,rson,L,R);
if(X<=mid) update_mul(lson,L,mid,v);
if(Y>mid) update_mul(rson,mid+1,R,v);
Sum[o]=(Sum[lson]+Sum[rson])%P;
}
}
ll s;
ll query(ll o,ll L,ll R) { //查询
ll mid=(L+R)/2;
ll lson=2*o,rson=2*o+1;
if(X<=L&&R<=Y) { //边界
return Sum[o];
}
push_down(o,lson,rson,L,R);
ll sum=0;
if(X<=mid) sum+=query(lson,L,mid);
if(Y>mid) sum+=query(rson,mid+1,R);
return sum%P;
}
int main() {
scanf("%lld%lld%lld",&n,&m,&P);
for(ll i=1; i<=n; i++) {
ll x;
scanf("%lld",&x);
a[i]=x;
}
build_tree(1,1,n);
for(ll i=1; i<=m; i++) {
ll opr;
scanf("%lld",&opr);
if(opr==1) {
ll v;
scanf("%lld%lld%lld",&X,&Y,&v);
if(X>Y) swap(X,Y);
update_mul(1,1,n,v);
}
if(opr==2) {
ll v;
scanf("%lld%lld%lld",&X,&Y,&v);
if(X>Y) swap(X,Y);
update_add(1,1,n,v);
}
if(opr==3) {
scanf("%lld%lld",&X,&Y);
if(X>Y) swap(X,Y);
s=query(1,1,n);
printf("%lld\n",s%P);
}
}
return 0;
}