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;
} 

posted @ 2018-10-10 07:31  Splitor  阅读(236)  评论(0编辑  收藏  举报