HaiHongOJ 1003 God Wang
题目连接:http://oj.haihongblog.com/problem.php?id=1003
线段树维护区间最小值,并且求解下标
#include <stdio.h> #include <vector> #include <algorithm> using namespace std; const int maxn=100000+10 ; const int INF=0x7FFFFFFF; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int N,K,zzt; vector<int> ans; int MIN[maxn<<2]; void PushUP(int rt) { MIN[rt]=min(MIN[rt<<1],MIN[rt<<1|1]); } void Build(int l,int r,int rt) { if(l==r) { scanf("%d",&MIN[rt]); return; } int m=(l+r)>>1; Build(lson); Build(rson); PushUP(rt); } void Update(int p,int add,int l,int r,int rt) { if(l==r) { MIN[rt]=add; return; } int m=(l+r)>>1; if(p<=m) Update(p,add,lson); else Update(p,add,rson); PushUP(rt); } int Query(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) return MIN[rt]; int m=(l+r)>>1; int ret=INF; if(L<=m) ret=min(ret,Query(L,R,lson)); if(R>m) ret=min(ret,Query(L,R,rson)); return ret; } void Find(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) { int lx=l,rx=r,node=rt; while(1) { int mx=(lx+rx)/2; if(lx==rx) {zzt=lx;break;} if(K>=MIN[2*node]) { node=2*node; rx=mx; continue; } if(K>=MIN[2*node+1]) { node=2*node+1; lx=mx+1; continue; } } return; } int m=(l+r)>>1; if(K>=MIN[rt<<1]&&L<=m) Find(L,R,lson); if(zzt!=-1) return; if(K>=MIN[rt<<1|1]&&R>m) Find(L,R,rson); if(zzt!=-1) return; } int main() { // freopen("F:\\test (1).in","r",stdin); // freopen("F:\\out.txt","w",stdout); while(~scanf("%d%d",&N,&K)){ Build(1,N,1); bool fail=0; int pos=1; ans.clear(); for(int i=1;i<=N;i++) { int P=Query(pos,N,1,N,1); if(K>=P) //后面一段存在可以吃的点 { zzt=-1; //找到第一个大于等于K的位置 zzt Find(pos,N,1,N,1); ans.push_back(zzt); pos=zzt; //该位置的值更新为INF Update(zzt,INF,1,N,1); K++; } else //后面一段不存在可以吃的点,从头开始找 { P=Query(1,N,1,N,1); if(K>=P) { zzt=-1; //找到第一个大于等于K的位置 zzt Find(1,N,1,N,1); ans.push_back(zzt); pos=zzt; //该位置的值更新为INF Update(zzt,INF,1,N,1); K++; } else //找不到了,失败 { fail=1; break; } } } if(fail) printf("-1\n"); else { for(int i=0;i<ans.size();i++) { printf("%d",ans[i]); if(i<ans.size()-1) printf(" "); else printf("\n"); } } } return 0; }