美文网首页
2020-07-09 【深基16.例7】普通二叉树(简化版)

2020-07-09 【深基16.例7】普通二叉树(简化版)

作者: JalorOo | 来源:发表于2020-07-09 22:53 被阅读0次

题目:https://www.luogu.com.cn/problem/P5076
使用STL: set

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;

/*快读*/
int read(){
    int x = 0,f = 1;
    char c = getchar();
    while (c<'0'||c>'9') {
        if (c=='-') {
            f = -1;
        }
        c = getchar();
    }
    while (c>='0'&&c<='9') {
        x = x*10+c-'0';
        c = getchar();
    }
    return x*f;
}

/*multiset有什么性质?
* 里面的元素按顺序排列,默认升序。
 * 不去重(这点和set是不同的)*/
multiset<int>q;
int n,t,x,order;

int main()
{
    q.insert(-0x7fffffff);
    q.insert(0x7fffffff);
    //提前放入这两个数,避免错误
    n = read();
    while(n--)
    {
        t = read();//功能
        x = read();//数字
        if(t==1)
        {
            multiset<int>::iterator it=q.lower_bound(x);
            //auto是自动判断数据类型,只有C++14以上才支持
            //可以写作multiset<int>::iterator,因为lower_bound方法返回的是迭代器
            // it 取得 x 的位置
            
            order=0;
            //order为排名
            
            for(multiset<int>::iterator i=q.begin();i!=it;i++,order++);
            //这里的auto同理,也是迭代器
            //这里就处理出了x的排名——order
            
            printf("%d\n",order);
            //输出order即为答案
        }
        else if(t==2)
        {
            order=-1;
            //初值为-1是因为前面有一个-0x7fffffff,所以order要多跑一步
            /*
            for(int i:q)
                if(++order==x)
                //缩写,order先自增一,再判断是否与x相等
                //如果是(order++==x),那就是先判断再自增,这里要尤其注意
                    printf("%d\n",i);
                //i就是容器里的值,输出i
             */
            //注意这里的for(:)循环,是只有C++11以上才支持的
            //和auto一样,都是noip不能用的
            //这种循环,i就是容器里的值而不是下标
            //也可以使用迭代器循环,上面的循环等价于
            
            for(multiset<int>::iterator it=q.begin();it!=q.end();it++)
            {
                order++;
                if(order==x)
                    printf("%d\n",*it);
            }
            
            //这种循环是noip可以使用的
        }
        else if(t==3)
        {
            multiset<int>::iterator it=q.lower_bound(x);
            //取得第一个大于等于x的值
            //也就是第一个x的位置
            //由于我们要取得前驱,所以it要自减一
            printf("%d\n",*(--it));
            //这句是先自减,再输出,是缩写
            //等价于:
            /*
                it--;
                printf("%d\n",*it);
            */
            //因为是迭代器(指针),所以输出前面加 *
        }
        else if(t==4)
        {
            printf("%d\n",*q.upper_bound(x));
            //要取得后继,就是第一个大于x的值
            //用upper_bound方法取得第一个大于x的迭代器
            //输出即可
            //因为是迭代器(指针),所以输出前面加 *
        }
        else
        {
            q.insert(x);
            //直接添加即可
        }
    }
    return 0;
}
/*
7
5 1
5 3
5 5
1 3
2 2
3 3
4 3
*/

非STL

#include<iostream>
#include<cstdio>
using namespace std;
const int INF=0x7fffffff;
int cont;
struct node{
    int val,ls,rs,cnt,siz;
}tree[500010];
int n,opt,xx;
void add(int x,int v)
{
    tree[x].siz++;
    if(tree[x].val==v){
        tree[x].cnt++;
        return ;
    }
    if(tree[x].val>v){
        if(tree[x].ls!=0)
          add(tree[x].ls,v);
        else{
            cont++;
            tree[cont].val=v;
            tree[cont].siz=tree[cont].cnt=1;
            tree[x].ls=cont;
        }
    }
    else{
        if(tree[x].rs!=0)
          add(tree[x].rs,v);
        else{
            cont++;
            tree[cont].val=v;
            tree[cont].siz=tree[cont].cnt=1;
            tree[x].rs=cont;
        }
    }
}
int queryfr(int x, int val, int ans) {
    if (tree[x].val>=val)
    {
        if (tree[x].ls==0)
            return ans;
        else
            return queryfr(tree[x].ls,val,ans);
    }
    else
    {
        if (tree[x].rs==0)
            return (tree[x].val<val) ? tree[x].val : ans;
        if (tree[x].cnt!=0)
            return queryfr(tree[x].rs,val,tree[x].val);
        else
            return queryfr(tree[x].rs,val,ans);
    }
}
int queryne(int x, int val, int ans) {
    if (tree[x].val<=val)
    {
        if (tree[x].rs==0)
            return ans;
        else
            return queryne(tree[x].rs,val,ans);
    }
    else
    {
        if (tree[x].ls==0)
            return (tree[x].val>val)? tree[x].val : ans;
        if (tree[x].cnt!=0)
            return queryne(tree[x].ls,val,tree[x].val);
        else
            return queryne(tree[x].ls,val,ans);
    }
}
int queryrk(int x,int rk)
{
    if(x==0) return INF;  
    if(tree[tree[x].ls].siz>=rk)   
        return queryrk(tree[x].ls,rk); 
    if(tree[tree[x].ls].siz+tree[x].cnt>=rk)   
        return tree[x].val; 
    return queryrk(tree[x].rs,rk-tree[tree[x].ls].siz-tree[x].cnt);
}
int queryval(int x,int val)
{
    if(x==0) return 0; 
    if(val==tree[x].val) return tree[tree[x].ls].siz+1; 
    if(val<tree[x].val) return queryval(tree[x].ls,val);
    return queryval(tree[x].rs,val)+tree[tree[x].ls].siz+tree[x].cnt;
}
inline int read()
{
    int r=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        r=(r<<3)+(r<<1)+(ch^48);
        ch=getchar();
    }
    return r*w;
}
int main()
{
    n=read();
    while(n--){
        opt=read();xx=read();
        if(opt==1) printf("%d\n",queryval(1,xx)+1);
        else if(opt==2) printf("%d\n",queryrk(1,xx));
        else if(opt==3) printf("%d\n",queryfr(1,xx,-INF));
        else if(opt==4) printf("%d\n",queryne(1,xx,INF));
        else{
            if(cont==0){
                cont++;
                tree[cont].cnt=tree[cont].siz=1;
                tree[cont].val=xx;
            }
            else add(1,xx);
        }
    }
    return 0;
}

以上题解搬运自洛谷

相关文章

网友评论

      本文标题:2020-07-09 【深基16.例7】普通二叉树(简化版)

      本文链接:https://www.haomeiwen.com/subject/tniecktx.html