线段树最大数
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树最大数相关的知识,希望对你有一定的参考价值。
最大数
使用数据结构线段树来维护区间的最大值。
树中的每个节点都代表一个区间,同时记录了一个当前记录区间的最大值。
树的结点个数为区间长度的4倍:视最后一层叶子节点个数为 N N N,那么所有的节点数之和为 2 N − 1 2N-1 2N−1,最后一层的节点可能还有分叉,节点个数最多为完全二叉树最后一层节点数目的2倍为 2 N 2N 2N,总的个数为 4 N − 1 4N-1 4N−1
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
int m,p;
struct node
{
int l,r;
int v;
}tr[4*N];
//子节点向父节点上更新
void pushup(int u)
{
tr[u].v = max(tr[u<<1].v,tr[u<<1|1].v);
}
//建树的操作,把每个节点的代表区间进行更新
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<<1,l,mid),build(u<<1|1,mid+1,r);
}
int query(int u,int l,int r)
{
//树中节点代表区间在查询区间之内直接返回树中记录的信息
if(tr[u].l >= l && tr[u].r <= r) return tr[u].v;
int mid = tr[u].l + tr[u].r >> 1;
//记录最大值,注意初始化
int v = 0;
//区间左边l小于等于mid
if(l <= mid) v = query(u<<1,l,r);
//区间右边r大于mid,取最大值
if(r > mid) v = max(v,query(u<<1|1,l,r));
return v;
}
//单点修改操作,从节点u开始,将x位置的值修改为v
void modify(int u,int x,int 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<<1,x,v);
else modify(u<<1|1,x,v);
pushup(u);//修改完要向上更新记录的最大值
}
}
int main()
{
int n = 0;
int last = 0;
scanf("%d%d",&m,&p);
build(1,1,m);
int x;
char s[2];
while(m--)
{
scanf("%s%d",s,&x);
if(s[0]=='Q')
{
last = query(1,n-x+1,n);
printf("%d\\n",last);
}
else
{
modify(1,n+1,(last+x)%p);
n++;
}
}
return 0;
}
以上是关于线段树最大数的主要内容,如果未能解决你的问题,请参考以下文章