[题解]牛的编号(POJ2182)

· · 个人记录

1. 题目大意

# 暴力解法 建立一个链表,每次根据大小关系从链表头部遍历插入 代码如下 ```cpp //AC 1144K 532ms #include<bits/stdc++.h> using namespace std; #define rg register #define ll long long #define ull unsigned long long namespace Enterprise{ inline int read(){ rg int s=0,f=0; rg char ch=getchar(); while(not isdigit(ch)) f|=(ch=='-'),ch=getchar(); while(isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48),ch=getchar(); return f?-s:s; } struct Node{ Node* nxt; int val,id; Node(){ nxt=NULL; val=0; } }; Node* head=new Node; int n; const int N=8015; int ans[N]; inline void main(){ n=read(); Node* first=new Node; first->id=1; head->nxt=first; for(rg int i=1;i<n;i++){ Node* now=new Node; rg int x=read(); now->id=i+1; Node* vis=new Node; vis=head; for(rg int i=1;i<=x;i++,vis=vis->nxt); now->nxt=vis->nxt; vis->nxt=now; } rg int i=1; for(Node *now=head->nxt;now;now=now->nxt,i++){ ans[now->id]=i; } for(rg int i=1;i<=n;i++){ printf("%d ",ans[i]); } } } signed main(){ Enterprise::main(); return 0; } ``` ~~OI生涯中第一次写对指针不RE,好开森~~ ~~略显笨拙~~ # 正解 权值线段树 本题说人话就是给出一个整数$n$,给出一个数列$\{a_n\}$,$a_i$代表除已选出数外区间$[1,n]$第$a_i$大。 所以我们就可以使用权值线段树较快解决此问题。 思路:每点代表一个区间,存放的数据为当前此区间内可供选择的数的数量。每次进行二分查找就可以得到答案 注意:由题意可得,前面的数有可能会影响后面的数,所以在选数顺序上,应注意采用倒序遍历,使其不会受到已选出的书的影响。 ```cpp //作者在考试的时候傻了,打的大暴力 //(尽管作者当时已经学习了主席树的思想 //AC 732K 110ms #include<bits/stdc++.h> using namespace std; #define rg register #define ll long long #define ull unsigned long long namespace Enterprise{ inline int read(){ rg int s=0,f=0; rg char ch=getchar(); while(not isdigit(ch)) f|=(ch=='-'),ch=getchar(); while(isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48),ch=getchar(); return f?-s:s; } const int N=8015; int tree[N<<2],n,a[N],ans[N]; #define ls (now<<1) #define rs (now<<1|1) #define mid ((l+r)>>1) inline void pushup(int now){ tree[now]=tree[ls]+tree[rs]; } inline void build(int now,int l,int r){ if(l==r){ tree[now]=1; return;} build(ls,l,mid); build(rs,mid+1,r); pushup(now); } inline int query(int now,int l,int r,int x){ if(l==r){ tree[now]--; return l; } rg int ans; if(x<=tree[ls]) ans=query(ls,l,mid,x); else ans=query(rs,mid+1,r,x-tree[ls]); pushup(now); return ans; } inline void main(){ n=read(); build(1,1,n); a[1]=1; for(rg int i=2;i<=n;i++) a[i]=read()+1; for(rg int i=n;i>=1;i--) ans[i]=query(1,1,n,a[i]); for(rg int i=1;i<=n;i++) printf("%d\n",ans[i]); } } signed main(){ Enterprise::main(); return 0; } ```