2017暑假訓練第二十天
今天早上的訓練研究了一下線段樹求最大值的演算法,建樹方法方法大致與模板相同,多了一個有關最大值的內容:
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);
}
}
}
}
下午的比賽中做出了兩道關於圖論的題,一道是最小生成樹,一道是最短路徑,都是近乎於模板的題,而且題意十分明顯,但是略有遺忘,所以總錯在小的細節上,還需再行復習這裡的相關知識和細節。還看了最後一道題(一道簡單的貪心題)但是不是我做出來的。
明天將繼續看有關於線段樹的知識點和題目的部落格。