ACM入门之线段树习题
Posted 辉小歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM入门之线段树习题相关的知识,希望对你有一定的参考价值。
目录
- 1275. 最大数【单点修改 区间最大】
- 245. 你能回答这些问题吗【单点修改 / 区间内的最大连续字段】
- 246. 区间最大公约数【区间修改 区间最大公约数】
- P3372 【模板】线段树 1【区间修改,区间查询】
- P2574 XOR的艺术【区间求1的个数 区间取反】
- 247. 亚特兰蒂斯【扫描线 求矩阵的面积】
1275. 最大数【单点修改 区间最大】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
struct nodeint l,r,v;tr[N*4];
int m,p;
void build(int u,int l,int r)//建树
tr[u]=l,r;
if(l==r) return;
int mid=tr[u].l+tr[u].r>>1;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
void pushup(int u)
tr[u].v=max(tr[u*2].v,tr[u*2+1].v);
int query(int u,int l,int r)
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v;//包含
else
int v=0,mid=(tr[u].l+tr[u].r)/2;
if(l<=mid) v=max(v,query(u*2,l,r));//左边有交集
if(r>=mid+1) v=max(v,query(u*2+1,l,r));//右边有交集
return v;
void modify(int u,int x,int v)
//u是根,x是位置,v是值
if(tr[u].l==x&&tr[u].r==x) tr[u].v=v;//叶子
else
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) modify(u*2,x,v);
else modify(u*2+1,x,v);
pushup(u);
int main(void)
cin>>m>>p;
build(1,1,m);
int last=0,n=0;
for(int i=0;i<m;i++)
char op; cin>>op;
if(op=='Q')
int x; cin>>x;
last=query(1,n-x+1,n);
cout<<last<<endl;
else
int x; cin>>x;
modify(1,n+1,(1ll*x+last)%p);
n++;
return 0;
245. 你能回答这些问题吗【单点修改 / 区间内的最大连续字段】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
struct node
int l,r;
int sum,tmax,lmax,rmax;
//sum: 区间和
//tmax:整个区间的最大子段和
//lmax:从左端点起的向右的最大子段和
//rmax:从右端点起的向左的最大子段和
tr[N*4];
int a[N],n,m;
void push(node& a,node& l,node& r)
a.sum=l.sum+r.sum;
a.tmax=max(l.tmax,r.tmax,l.rmax+r.lmax,l.sum+r.lmax,r.sum+l.rmax,);
a.lmax=max(l.lmax,l.sum+r.lmax);
a.rmax=max(r.rmax,r.sum+l.rmax);
void pushup(int u)
push(tr[u],tr[u*2],tr[u*2+1]);
void build(int u,int l,int r)
if(l==r) tr[u]=l,r,a[l],a[l],a[l],a[l];
else
tr[u]=l,r;
int mid=l+r>>1;
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
void modify(int u,int x,int v)
if(tr[u].l==x&&tr[u].r==x)
tr[u]=x,x,v,v,v,v;
else
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=x) modify(u*2,x,v);
else modify(u*2+1,x,v);
pushup(u);
node query(int u,int l,int r)
if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
else
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=r) return query(u*2,l,r);
else if(l>mid) return query(u*2+1,l,r);
else
auto left=query(u*2,l,r);
auto right=query(u*2+1,l,r);
node res;
push(res,left,right);
return res;
int main(void)
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
for(int i=0;i<m;i++)
int op,x,y; cin>>op>>x>>y;
if(op==1)
if(x>y) swap(x,y);
auto temp=query(1,x,y);
cout<<temp.tmax<<endl;
else modify(1,x,y);
return 0;
246. 区间最大公约数【区间修改 区间最大公约数】
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
LL gcd(LL a,LL b)return b?gcd(b,a%b):a;
struct node
int l,r;
LL sum,d;//sum区间总和,d区间最大公约数
tr[N*4];
LL n,m,a[N];
void push(node& u,node& l,node& r)
u.sum=l.sum+r.sum;
u.d=gcd(l.d,r.d);
void pushup(int u)
push(tr[u],tr[u*2],tr[u*2+1]);
void build(int u,int l,int r)
if(l==r)
LL b=a[l]-a[l-1];
tr[u]=l,r,b,b;
else
tr[u]=l,r;
int mid=l+r>>1;
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
void modify(int u,int x,LL c)
if(tr[u].l==x&&tr[u].r==x)
tr[u].sum+=c,tr[u].d+=c;
return;
else
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=x) modify(u*2,x,c);
else modify(u*2+1,x,c);
pushup(u);
node query(int u,int l,int r)
if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
else
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=r) return query(u*2,l,r);
else if(l>=mid+1) return query(u*2+1,l,r);
else
auto left=query(u*2,l,r);
auto right=query(u*2+1,l,r);
node res;
push(res,left,right);
return res;
int main(void)
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
for(int i=1;i<=m;i++)
char op; cin>>op;
if(op=='C')
LL l,r,d; cin>>l>>r>>d;
modify(1,l,d);
if(r+1<=n) modify(1,r+1,-d);
else
int l,r; cin>>l>>r;
node right=0,0,0,0;
auto left=query(1,1,l);
if(l+1<=n) right=query(1,l+1,r);
printf("%lld\\n",labs(gcd(left.sum,right.d)));
return 0;
P3372 【模板】线段树 1【区间修改,区间查询】
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5+10;
struct node
int l,r;
LL sum,add;
tr[N*4];
LL a[N],n,m;
void pushup(int u)
tr[u].sum=tr[u*2].sum+tr[u*2+1].sum;
void pushdown(int u)//根节点更新,子结点
auto &ans=tr[u];
auto &l=tr[u*2];
auto &r=tr[u*2+1];
if(ans.add)
l.sum+=(l.r-l.l+1)*ans.add;
r.sum+=(r.r-r.l+1)以上是关于ACM入门之线段树习题的主要内容,如果未能解决你的问题,请参考以下文章