2017暑假训练第二十天

来源:互联网 发布:淘宝助理使用教程视频 编辑:程序博客网 时间:2024/05/21 21:42

  今天早上的训练研究了一下线段树求最大值的算法,建树方法方法大致与模板相同,多了一个有关最大值的内容:

  tree[id].max=max(tree[2*id].tree[2*id+1]);

  意思也很好理解,就是根节点的最大值等于左子区间和右子区间的最大值的较大者,依旧是递归查找类型。

  而后a了一道插入元素并查询第k大数的题目,就是一开始建立一个空的树,根据插入的元素与位置的关系向树里插入元素,并进行查询。

  代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 1000005
using namespace std;
struct xtree{
    int l;
    int r;
    int val;
    int mid(){
        return (l+r)/2;
    }
};
struct xtree tree[maxn*3];
int n,m;
int pushup(int id){
    tree[id].val=tree[id*2].val+tree[id*2+1].val;
}
void build(int id,int l,int r){
    tree[id].l=l;
    tree[id].r=r;
    tree[id].val=0;
    if (tree[id].l==tree[id].r){
        return ;
    }
    int mm=tree[id].mid();
    build(id*2,l,mm);
    build(id*2+1,mm+1,r);
    pushup(id);
}
void update(int id,int l,int r,int pos){
    if (l==r){
        tree[id].val++;
        return ;
    }
    int mm=tree[id].mid();
    if (pos>mm)update(id*2+1,mm+1,r,pos);
    else update(id*2,l,mm,pos);
    pushup(id);
}
int query(int id,int l,int r,int pos){
    int re;
    if (l==r){
        return l;
    }
    else {
        int mm=tree[id].mid();
        if (pos>tree[id*2].val)re=query(id*2+1,mm+1,r,pos-tree[id*2].val);
        else re=query(id*2,l,mm,pos);
    }
    return re;
}
int main(){
    int i,j,k;
    while(scanf("%d%d",&n,&m)!=EOF){
        int sum=0;
        build(1,1,maxn);
        char str[2];
        int num;
        for(i=0;i<n;i++){
            scanf("%s",str);
            if(str[0]=='I'){
                sum++;
                scanf("%d",&num);
                update(1,1,n,num);
            }
            else if(str[0]=='Q'){
                int ans=query(1,1,maxn,sum-m+1);
                printf("%d\n",ans);
            }
        }
    }
}

  下午的比赛中做出了两道关于图论的题,一道是最小生成树,一道是最短路径,都是近乎于模板的题,而且题意十分明显,但是略有遗忘,所以总错在小的细节上,还需再行复习这里的相关知识和细节。还看了最后一道题(一道简单的贪心题)但是不是我做出来的。

  明天将继续看有关于线段树的知识点和题目的博客。

原创粉丝点击