首页 > 其他 > 详细

2018南京网络赛G

时间:2018-09-01 21:06:21      阅读:176      评论:0      收藏:0      [点我收藏+]

一道模拟题,每次给一个值只需要找从左到右第一个小于它的值,用线段树维护一个区间最小值即可。

只有当左儿子的最小值大于当前值才去找右儿子。

当时好像我们集体读错题了,但是我的代码依然可以a,不过忘了判断kkk是不是-1是真的真的真的很难受。

 

 

技术分享图片
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include <bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define up rt,rt<<1,rt<<1|1
using namespace std;
typedef long long ll;
const int M = 1e5+7;
const ll inf = 1e18;
int n,q,ans[M*2],p[M<<3],pos;
ll m,a[M*2];
ll mn[M<<3],r[M*2];
void pushup(int rt,int l,int r){
    mn[rt]=min(mn[l],mn[r]);
}
void build(int l,int r,int rt){
    if(l==r){
        mn[rt]=a[l];
        p[rt]=l;
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(up);
}
void update(int l,int r,int rt){
    if(l==r){
        mn[rt]=inf;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) update(lson);
    else update(rson);
    pushup(up);
}
int query(int l,int r,int rt,ll k){
    if(l==r){
        return rt;
    }
    int mid=(l+r)>>1;
    if(mn[rt<<1]<=k) return query(lson,k);
    else return query(rson,k);
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    scanf("%d%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,n,1);
    ll res=0;ans[0]=0;int tot=0,kkk=-1;
    for(int i=1;i<=100005;i++){
        res+=m;
        if(res<mn[1]){
            ans[i]=ans[i-1];r[i]=res;
        }
        else{
            int tmp=0;
            while(res>=mn[1]){
                int qq=query(1,n,1,res);
                res-=mn[qq];pos=p[qq];
                update(1,n,1);
                tmp++;tot++;
                if(tot==n){
                    kkk=i;
                    break;
                }
            }
            ans[i]=ans[i-1]+tmp;r[i]=res;
        }
        if(kkk!=-1) break;
        //cout<<mn[1]<<endl;
    }
    if(kkk!=-1){//rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrri shit
        for(int i=kkk+1;i<=100005;i++){
            ans[i]=ans[kkk];r[i]=r[kkk];
        }
    }
    scanf("%d",&q);
    while(q--){
        int d;
        scanf("%d",&d);
        printf("%d %lld\n",ans[d],r[d]);
    }
    return 0;
}
View Code

 

2018南京网络赛G

原文:https://www.cnblogs.com/LMissher/p/9571403.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!