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;
}

 

posted @ 2015-11-25 09:47  Fighting_Heart  阅读(157)  评论(0编辑  收藏  举报