前幾天學習了劃分樹和sbt,一直沒機會訓練一下,今天實驗室有網了,就訓練poj上面一道水題。分別用兩種資料結構來實現了一下!
這道題題目很簡單,就是給定序列,求區間最小值!
sbt:
#include#include
using
namespace std;
#define m 100005
struct sbttree[m];
int root,top;
int a[m];
struct queryque[m/2];
bool cmp(const query &q1,const query &q2)
return q1.ql}
bool cmp2(const query &q1,const query &q2)
void init()
//這兩種旋轉看起來是挺容易的,但自己寫容易混亂,最好能結合圖
void rotate_left(int &x)
void rotate_right(int &x)
void maintain(int &x,bool flag)else
if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)else
return ;
}elseelse
if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)else
return ;
} maintain(tree[x].left,false);
maintain(tree[x].right,true);
maintain(x,false);
maintain(x,true);
} /*
* 這裡用陣列實現,遞迴插入,挺巧妙的,我自己用陣列做的時候都不會想到這樣做
* tree的0位置空著不用; 帥氣,如果不進行調整的話,root能保持root=1
* */
void insert(int &x,int key)else
} //這裡要保證刪除的資料存在
void remove(int &x,int key)else
if(keyremove(tree[x].left,key);
}elseelse
if(tree[x].right!=0&&tree[x].left==0)else
if(tree[x].left==0&&tree[x].right==0)else
} }
//求第k小的數
int select(int &x,int k)
int main()
int ql,qr,k;
for(i=0;iscanf("%d %d %d",&ql,&qr,&k);
que[i].id=i;
que[i].k=k;
que[i].ql=ql;
que[i].qr=qr;
} sort(que,que+m,cmp);
for(i=que[0].ql;i<=que[0].qr;i++)
que[0].ans=select(root,que[0].k);
for(i=1;i//前乙個區間與當前區間只有兩種關係,相交或者不相交
if(que[i].ql<=que[i-1].qr)
} //看終點
if(que[i].qr//
for(j=que[i].qr+1;j<=que[i-1].qr;j++)
}else
if(que[i].qr>que[i-1].qr)
} }else
for(j=que[i].ql;j<=que[i].qr;j++)
} que[i].ans=select(root,que[i].k);
} sort(que,que+m,cmp2);
for(i=0;iprintf("%d\n",que[i].ans);
} return 0; }
劃分樹:
#include#include
using
namespace std;
#define m 100005
int tree[30][m];
int toleft[30][m];
int sorted[m];
int n,m;
void build(int level,int left,int right)
} int lpos=left,rpos=mid+1;
for(i=left;i<=right;i++)else
if(tree[level][i]toleft[level][i]++;
tree[level+1][lpos++]=tree[level][i];
}else
if(tree[level][i]>sorted[mid])elseelse
} }
build(level+1,left,mid);
build(level+1,mid+1,right);
} int query(int level,int left,int right,int ql,int qr,int k)
int s,ss;
int mid=(left+right)>>1;
if(left==ql)else
int nql,nqr;
if(k<=ss)else
return 0;
} int main()
sort(sorted+1,sorted+n+1);
build(0,1,n);
int ql,qr,k;
for(int i=0;iscanf("%d %d %d",&ql,&qr,&k);
int ans=query(0,1,n,ql,qr,k);
printf("%d\n",ans);
} return 0; }
求素數的兩種解法
檔名 exp1 1.cpp 求素數的個數 include include bool prime int n 判斷正整數n是否是素數 int main for i 3 i n i 2 printf n return 0 檔名 exp1 1 2.cpp 利用快速篩選法求素數的個數 篩法的思想是去除要求範...
主席樹,查詢區間的第k小值
學習報告 主席樹真的nb,如果樸素做要開n個線段樹,記憶體 優化的方式,每次插入乙個數,並不是整個權值線段樹都改變了,只是改變logn個節點,我們只需要多開logn個節點就ok,用root陣列記錄歷史個線段樹版本,詢問區間,可以做相減,詢問第k小值,與左樹的所有節點sum作比較,如果小就在左邊,否則...
「取最大的K的數」的兩種解法
輸入n個整數,輸出其中最大的k個。例如輸入1,2,3,4,5,6,7和8這8個數字,則最小的4個數字為5,6,7和8。開乙個容量為k的最小堆。每次來乙個數,比較堆頂 最小值 和這個數誰大,如果當前的數更大,就替換掉堆頂。時間複雜度 o nlogk 優點 對於海量資料 流 可以用o k 的記憶體搞定 ...