題解 P1801 【黑匣子_NOI導刊2010提高(06)】
阿新 • • 發佈:2018-02-24
amp 平衡樹 clu 實現 cto ctype 一位 mark 排序
我看正解已經有一大堆了,我就發個不太正經的吧
最近不會高級數據結構的蒟蒻在搞STL,搞完普通平衡樹後就看到了這道題,本來想用黑科技pb_ds中的紅黑樹做的,發現已經有大佬貼了一篇。set的做法也有人發了。
然後蒟蒻的我又想出一個歪法---暴力模擬!!!
- 你要知道:
首先介紹個STL中應該挺少人知道的函數nth_element(),顧名思義,就是求出區間內第n大的元素,搞這道題剛好合適。
- 使用:
它的使用也非常方便,直接調用nth_element(pos1,pos2,pos3),
參數介紹:
pos1是區間的開始位置
pos2是你要查的元素的在排序後位置,見下面代碼實現,一看就懂
pos3是區間結束的下一個位置
所以pos1,pos3其實是個左閉右開的區間,如果你不知道這什麽意思你就記著pos3是要越界的
其他:
這個時間復雜度好像是O(NlogN),但是不開O2 有80分,開了O2 90分。
STL真是個救急的神器,非常適合對拍
我的代碼裏還有另一用vector實現方法,但只有50分就不介紹了,有興趣的可以看一下
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <vector> #include <cctype> #pragma GCC optimize(3) #define ll int using namespace std; const int maxn=200010; int n,m; void print(int x) { if(x<0){//負數 putchar(‘-‘); x=-x; } if(x>9) print(x/10); //遞歸完後棧裏面x的每一位是倒過來的 putchar(x%10+‘0‘); } ll add[maxn],Get[maxn]; ll read() { ll x=0;char ch;short int neg=0;ch=getchar(); while(!isdigit(ch)){ neg|=(ch==‘-‘);ch=getchar(); } while(isdigit(ch)){ x=x*10+ch-48;ch=getchar(); } return neg?-x:x; } void solve_1() { vector <ll>a; int cnt=1,node=0; cin>>m>>n; for(register int i=1;i<=m;i++)add[i]=read(); for(register int i=1;i<=n;i++)Get[i]=read(); sort(Get+1,Get+1+n); for(register int i=1;i<=m&&cnt<=n+1;i++) { ll x=add[i]; a.insert(upper_bound(a.begin(),a.end(),x),x); while(i==Get[cnt]&&cnt<=n+1) { cout<<a[++node-1]<<endl; cnt++; } } } void solve_2() { int cnt=1,node=0; ll a[maxn]; cin>>m>>n; for(register int i=1;i<=m;i++)add[i]=read(); for(register int i=1;i<=n;i++)Get[i]=read(); sort(Get+1,Get+1+n); for(register int i=1;i<=m&&cnt<=n+1;i++) { a[i]=add[i]; while(i==Get[cnt]&&cnt<=n+1) { nth_element(a+1,a+(++node),a+i+1); printf("%d\n",a[node]);//print(a[node]);putchar(‘\n‘); cnt++; } } } int main() { //solve_1(); solve_2(); return 0; }
感覺這篇題解太水了-逃)
題解 P1801 【黑匣子_NOI導刊2010提高(06)】