您的位置:首页 > Web前端 > JavaScript

线段树——BZOJ1012/Luogu1198 [JSOI2008]最大数

2017-03-24 11:06 260 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=1012

https://www.luogu.org/problem/show?pid=1198

经典老题现在才AC。。。

这题方法很多,有单调栈,有线段树,有树状数组……

我是用线段树写的

其实就是胜者树求区间最大

我们建一棵大小为m的线段树,每个节点赋值为-2^30,然后插入节点(其实就是修改)和询问都是模板了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
char c[5];
ll m,d,q=0,n=0;
ll t[800001]={0},lt[800001],rt[800001];
inline void build(ll l,ll r,ll nod){
t[nod]=-1<<30;lt[nod]=l;rt[nod]=r;
if(l==r)return;
ll mid=(l+r)>>1;
build(l,mid,nod*2);
build(mid+1,r,nod*2+1);
}
inline void xg(int i,int p,int nod){
if(lt[nod]==i&&rt[nod]==i)t[nod]=p;
else{
ll mid=(lt[nod]+rt[nod])>>1;
if(i>mid)xg(i,p,nod*2+1);
else xg(i,p,nod*2);
t[nod]=max(t[nod*2],t[nod*2+1]);
}
}
inline ll s(int i,int j,int nod){
if(lt[nod]==i&&rt[nod]==j)return t[nod];
ll mid=(lt[nod]+rt[nod])>>1;
if(j<=mid)return s(i,j,nod*2);
if(i>=mid+1)return s(i,j,nod*2+1);
ll le=s(i,mid,nod*2),re=s(mid+1,j,nod*2+1);
return max(le,re);
}
int main()
{
scanf("%lld%lld",&m,&d);
build(1,m,1);
ll x;
for(int i=1;i<=m;i++){
scanf("%s",c);
scanf("%lld",&x);
if(c[0]=='A'){
n++;xg(n,(x+q)%d,1);
}else{
q=s(n-x+1,n,1);
printf("%lld\n",q);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树