deda:用线段树实现竞赛树的思想
竞赛树图解:
本道题目的实现:
1、建一颗空树
2、每当修改一个选手的实力时要重赛,即update
3、查询时优先递归左孩子,没有再递归右孩子(注意有些地方和线段树是由差别的)
code:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define int long long
#define half (l+r)>>1
const int INF = 1e17;
const int maxn=2000006;
struct hzw
{
int lc,rc,mx;
}t[maxn];
int n,q,tot;
inline void build (int s,int l,int r)
{
t[s].mx = INF;
if (l == r)
{
return;
}
int mid = half;
t[s].lc = ++tot;
build (t[s].lc,l,mid);
t[s].rc = ++tot;
build (t[s].rc,mid+1,r);
}
inline void update (int s,int l,int r,int p,int x)
{
if (l == p&&r == p)
{
t[s].mx = x;
return ;
}
int mid = half;
if (p <= mid) update (t[s].lc,l,mid,p,x);
else update (t[s].rc,mid+1,r,p,x);
t[s].mx = min (t[t[s].lc].mx,t[t[s].rc].mx);
}
inline int query (int s,int l,int r,int cl,int cr,int k)
{
if (l==r)
{
return l;
}
int mid = half;
if (cl>mid)
{
if (t[t[s].rc].mx > k) return INF;
return query (t[s].rc,mid+1,r,cl,cr,k);
}
else
{
int tmp1= t[t[s].lc].mx > k ? INF:query(t[s].lc,l,mid,cl,mid,k);
if (tmp1 < INF) return tmp1;
int tmp2 =t[t[s].rc].mx > k ? INF:query(t[s].rc,mid+1,r,mid+1,cr,k);
return tmp2;
}
}
signed main()
{
tot=1;
cin>>n>>q;
build(1,1,n);
for (int i=1,a,b;i<=q;++i)
{
char cur;
scanf("%s",&cur);
if (cur == 'M')
{
scanf("%lld%lld",&a,&b);
update (1,1,n,b,a);
}
else
{
scanf("%lld%lld",&a,&b);
int tmp = query (1,1,n,b,n,a);
tmp = tmp == INF ? -1 : tmp;
printf("%lld\n",tmp);
}
}
return 0;
}