# include<iostream>
# include<cstring>
using namespace std;
const int N = 2e5+10;
struct node{
int l,r;
int v;
}tr[4*N];/*存树,按照4倍储存空间储存*/
/*
线段树的存图形式为顶点为u,他的左儿子为u*2,右儿子为u*2+1
用位运算优化为左儿子:u<<1
右儿子:u<<1|1
*/
void build(int u,int l,int r)/*初始化建图*/
{
tr[u] = {l,r};/*顶点u的左右边界为[l,r]*/
if(l == r) return;/*如果左右边界相同,也就是说该点为顶点,而不是线段*/
int mid = l+r>>1;/*取中点*/
build(u<<1,l,mid),build(u<<1|1,mid+1,r);/*分别建立两段线段*/
}
void pushup(int u)/*根据子节点来更新根节点的数据*/
{
tr[u].v = max(tr[u<<1].v,tr[u<<1|1].v);/*跟节点的值为左右节点值的最大值*/
}
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;/*取中点,将线段分为[l,mid],[mid+1,r]两段*/
int v = 0;
if(l <= mid) v = query(u<<1,l,r);/*如果在左区间则查询左边*/
if(r > mid) v = max(v,query(u<<1|1,l,r));/*如果在右边则查询右边的最大值*/
return v;
}
void modify(int u,int x,int v)/*单点修改*/
{
if(tr[u].l == x && tr[u].r == x) tr[u].v = v;/*如果该节点的左右区间都为X说明这就是要修改的单点*/
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);/*因为子节点的值被修改,根节点的值有可能被影响,所以需要pushup更新一遍*/
}
}
int m,p;/*m表示操作次数,p是数据需要%的值*/
int main(){
int n = 0,last = 0;
cin>>m>>p;
build(1,1,m);
int x;
char op[2];
while(m--)
{
scanf("%s%d",op,&x);
if(*op == 'Q')
{ /*如果是Q则查询*/
last = query(1,n-x+1,n);
cout<<last<<endl;
}
else
{ /*否则就修改单点的值*/
modify(1,n+1,((long long)last+x)%p);
n++;/*n表示线段的最大长度*/
}
}
return 0;
}
标签:int,线段,tr,mid,query,节点,模板 来源: https://www.cnblogs.com/empty-y/p/15943721.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。