目录
树状数组1(单点修改,区间查询)
题目链接: https://www.luogu.com.cn/problem/P3374
代码:
// Problem: P3374 【模板】树状数组 1
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3374
// Memory Limit: 512 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5+5;
int n,q;
int a[N];
struct node{
ll t,val,sz,l,r;
}seg[N*4];
void update(int id){
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void settag(int id,ll t){
seg[id].t=seg[id].t+t;
seg[id].val=seg[id].val+seg[id].sz*t;
}
void pushdown(int id){
if(seg[id].t!=0){
settag(id*2,seg[id].t);
settag(id*2+1,seg[id].t);
seg[id].t=0;
}
}
void build(int id,int l,int r){
seg[id].sz=r-l+1;
if(l==r){
seg[id].val={a[l]};
}
else{
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
}
void change(int id,int l,int r,int pos,ll val){
if(l==r){
seg[id].val=seg[id].val+val;
return;
}
int mid=(l+r)/2;
if(pos<=mid){
change(id*2,l,mid,pos,val);
}
else if(pos>mid){
change(id*2+1,mid+1,r,pos,val);
}
update(id);
}
ll query(int id,int l,int r,int ql,int qr){
if(ql==l&&qr==r){
return seg[id].val;
}
int mid=(l+r)/2;
pushdown(id);
if(qr<=mid){
return query(id*2,l,mid,ql,qr);
}
else if(ql>mid){
return query(id*2+1,mid+1,r,ql,qr);
}
else{
return query(id*2,l,mid,ql,mid)+query(id*2+1,mid+1,r,mid+1,qr);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=0;i<q;i++){
int ty;
cin>>ty;
if(ty==1){
int x,d;
cin>>x>>d;
change(1,1,n,x,d);
}
else{
int l,r;
cin>>l>>r;
cout<<query(1,1,n,l,r)<<"\n";
}
}
return 0;
}
树状数组2(区间修改,单点查询)
题目链接: https://www.luogu.com.cn/problem/P3368
代码:
// Problem: P3372 【模板】线段树 1
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3372
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5+5;
int n,q;
int a[N];
struct node{
ll t,val,sz,l,r;
}seg[N*4];
void update(int id){
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void settag(int id,ll t){
seg[id].t=seg[id].t+t;
seg[id].val=seg[id].val+seg[id].sz*t;
}
void pushdown(int id){
if(seg[id].t!=0){
settag(id*2,seg[id].t);
settag(id*2+1,seg[id].t);
seg[id].t=0;
}
}
void build(int id,int l,int r){
seg[id].sz=r-l+1;
if(l==r){
seg[id].val={a[l]};
}
else{
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
}
void modify(int id,int l,int r,int ql,int qr,ll t){
if(l==ql&&r==qr){
settag(id,t);
return;
}
int mid=(l+r)/2;
pushdown(id);
if(qr<=mid){
modify(id*2,l,mid,ql,qr,t);
}
else if(ql>mid){
modify(id*2+1,mid+1,r,ql,qr,t);
}
else{
modify(id*2,l,mid,ql,mid,t);
modify(id*2+1,mid+1,r,mid+1,qr,t);
}
update(id);
}
ll query(int id,int l,int r,int pos){
if(r==l){
return seg[id].val;
}
int mid=(l+r)/2;
pushdown(id);
if(pos<=mid){
return query(id*2,l,mid,pos);
}
else if(pos>mid){
return query(id*2+1,mid+1,r,pos);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=0;i<q;i++){
int ty;
cin>>ty;
if(ty==1){
int l,r,d;
cin>>l>>r>>d;
modify(1,1,n,l,r,d);
}
else{
int x;
cin>>x;
cout<<query(1,1,n,x)<<"\n";
}
}
return 0;
}
线段树1(区间修改,区间查询)
题目链接: https://www.luogu.com.cn/problem/P3372
代码:
// Problem: P3372 【模板】线段树 1
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3372
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
int n,q;
int a[N];
struct node{
ll t,val,sz;
}seg[N*4];
void update(int id){
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void settag(int id,ll t){
seg[id].t=seg[id].t+t;
seg[id].val=seg[id].val+seg[id].sz*t;
}
void pushdown(int id){
if(seg[id].t!=0){
settag(id*2,seg[id].t);
settag(id*2+1,seg[id].t);
seg[id].t=0;
}
}
void build(int id,int l,int r){
seg[id].sz=r-l+1;
if(l==r){
seg[id].val={a[l]};
}
else{
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
}
void modify(int id,int l,int r,int ql,int qr,ll t){
if(l==ql&&r==qr){
settag(id,t);
return;
}
int mid=(l+r)/2;
pushdown(id);
if(qr<=mid){
modify(id*2,l,mid,ql,qr,t);
}
else if(ql>mid){
modify(id*2+1,mid+1,r,ql,qr,t);
}
else{
modify(id*2,l,mid,ql,mid,t);
modify(id*2+1,mid+1,r,mid+1,qr,t);
}
update(id);
}
ll query(int id,int l,int r,int ql,int qr){
if(l==ql&&r==qr){
return seg[id].val;
}
int mid=(l+r)/2;
pushdown(id);
if(qr<=mid){
return query(id*2,l,mid,ql,qr);
}
else if(ql>mid){
return query(id*2+1,mid+1,r,ql,qr);
}
else{
return query(id*2,l,mid,ql,mid)+query(id*2+1,mid+1,r,mid+1,qr);
}
}
int main(){
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=0;i<q;i++){
int ty;
cin>>ty;
if(ty==1){
int l,r,d;
cin>>l>>r>>d;
modify(1,1,n,l,r,d);
}
else{
int l,r;
cin>>l>>r;
cout<<query(1,1,n,l,r)<<"\n";
}
}
return 0;
}
代码源线段树1(查询最小值出现次数)
题目链接: http://oj.daimayuan.top/course/15/problem/654
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
const int inf = 0x3f3f3f3f;
int n,q;
int a[N];
struct info{
};
info operator +(const info &l,const info &r){
info a;
a.minv=min(l.minv,r.minv);
if(l.minv==r.minv){
a.mincnt=l.mincnt+r.mincnt;
}
else if(l.minv<r.minv){
a.mincnt=l.mincnt;
}
else{
a.mincnt=r.mincnt;
}
return a;
}
struct node{
info val;
}seg[N*4];
void update(int id){
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void build(int id,int l,int r){
if(l==r){
seg[id].val={a[l],1};
}
else{
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
}
void change(int id,int l,int r,int pos,int val){
if(l==r){
seg[id].val={val,1};
//a[pos]=val;
}
else{
int mid=(l+r)/2;
if(pos<=mid){
change(id*2,l,mid,pos,val);
}
else{
change(id*2+1,mid+1,r,pos,val);
}
update(id);
}
}
info query(int id,int l,int r,int ql,int qr){
if(l==ql&&r==qr){
return seg[id].val;
}
int mid=(l+r)/2;
if(qr<=mid){
return query(id*2,l,mid,ql,qr);
}
else if(ql>mid){
return query(id*2+1,mid+1,r,ql,qr);
}
else{
return query(id*2,l,mid,ql,mid)+query(id*2+1,mid+1,r,mid+1,qr);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=0;i<q;i++){
int ty;
cin>>ty;
if(ty==1){
int x,d;
cin>>x>>d;
change(1,1,n,x,d);
}
else{
int l,r;
cin>>l>>r;
auto ans=query(1,1,n,l,r);
cout<<ans.minv<<' '<<ans.mincnt<<"\n";
}
}
return 0;
}
代码源线段树2(最大字段和)
题目链接:
目录
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
const int inf = 0x3f3f3f3f;
int n,q;
int a[N];
struct info{
ll mss,mpre,msuf,s;
info(){}
info(int a):mss(a),mpre(a),msuf(a),s(a){}
};
info operator +(const info &l,const info &r){
info a;
a.mss=max({l.mss,r.mss,l.msuf+r.mpre});
a.mpre=max(l.mpre,l.s+r.mpre);
a.msuf=max(r.msuf,r.s+l.msuf);
a.s=l.s+r.s;
return a;
}
struct node{
info val;
}seg[N*4];
void update(int id){
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void build(int id,int l,int r){
if(l==r){
seg[id].val=info(a[l]);
}
else{
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
}
void change(int id,int l,int r,int pos,int val){
if(l==r){
seg[id].val=info(val);
//a[pos]=val;
}
else{
int mid=(l+r)/2;
if(pos<=mid){
change(id*2,l,mid,pos,val);
}
else{
change(id*2+1,mid+1,r,pos,val);
}
update(id);
}
}
info query(int id,int l,int r,int ql,int qr){
if(l==ql&&r==qr){
return seg[id].val;
}
int mid=(l+r)/2;
if(qr<=mid){
return query(id*2,l,mid,ql,qr);
}
else if(ql>mid){
return query(id*2+1,mid+1,r,ql,qr);
}
else{
return query(id*2,l,mid,ql,mid)+query(id*2+1,mid+1,r,mid+1,qr);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=0;i<q;i++){
int ty;
cin>>ty;
if(ty==1){
int x,d;
cin>>x>>d;
change(1,1,n,x,d);
}
else{
int l,r;
cin>>l>>r;
auto ans=query(1,1,n,l,r);
cout<<ans.mss<<"\n";
}
}
return 0;
}
动态开点
https://www.luogu.com.cn/problem/P2781
#include<cstdio>//动态开点线段树是一类特殊的线段树,与普通的线段树不同的是,每一个节点的左右儿子不是该点编号的两倍和两倍加一,而是现加出来的
#include<iostream>//https://blog.csdn.net/u012972031/article/details/88751811 https://www.cnblogs.com/szbszb/p/11243728.html
#include<cstring>
#define int long long
using namespace std;
const int N=1e7+10;
struct node {
int ls,rs,lazy;//左儿子地址,右儿子地址,延迟标记
long long sum;//区间和
} tr[N*4];
int root=0,cnt=0;//根据insert代码(11行),root从1开始
void init() {
memset(tr,0,sizeof(tr));
root=0,cnt=0;
}
void insert(int &root,int l,int r,int ll,int rr,int x) { //建树&&区间修改 root区间范围[l,r],修改范围[ll,rr],修改增量x root是人为规定的编号,涉及修改,传引用
if(!root)root=++cnt;//root还没开,开点
int len=min(r,rr)-max(l,ll)+1;//b为修改区间在当前区间的长度 例如真子集[1,N],修改[10,20],b=20-10+1=11 或者交集[50,100],修改[30,70],b=70-50+1 =21
if(len<0) return;//或者空集[50,100]修改[10,20] b=20-50+1 =-29 <0
tr[root].sum+=len*x;
if(l>=ll&&r<=rr) { //真子集
tr[root].lazy+=x;
return;
}
int mid=l+r>>1;
if(ll<=mid)insert(tr[root].ls,l,mid,ll,rr,x);
if(rr>mid)insert(tr[root].rs,mid+1,r,ll,rr,x);
}
int query(int root,int l,int r,int ll,int rr) {//区间查询,在范围为[l,r]的root中查询[ll,rr]的区间和
if(l>=ll&&r<=rr)return tr[root].sum;//真子集
int mid=l+r>>1;
if(tr[root].lazy) {//下放延迟标记
if(!tr[root].ls) tr[root].ls=++cnt;
tr[tr[root].ls].lazy+=tr[root].lazy;
tr[tr[root].ls].sum+=tr[root].lazy*(mid-l+1);
if(!tr[root].rs) tr[root].rs=++cnt;
tr[tr[root].rs].lazy+=tr[root].lazy;
tr[tr[root].rs].sum+=tr[root].lazy*(r-mid);
tr[root].lazy=0;
}
long long ans=0;
if(ll<=mid) ans+=query(tr[root].ls,l,mid,ll,rr);
if(rr>mid) ans+=query(tr[root].rs,mid+1,r,ll,rr);
return ans;
}
signed main() {
ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
// for(int i=1; i<=n; i++) {
// int temp;
// cin>>temp;
// insert(root,1,n,i,i,temp);
// }
for(int i=1; i<=m; i++) {
int ta,tb,tc,td;
cin>>ta>>tb>>tc;
if(ta==1) {
cin>>td;
insert(root,1,n,tb,tc,td);
} else if(ta==2) {
cout<<query(root,1,n,tb,tc)<<endl;
}
}
return 0;
}