CodeForces 1439 - Problem C - Greedy Shopping - 吉司机线段树

这题实在把我心态搞崩了
WA了一万发
错误答案吧先留着吧,以后补,今天实在没心情补了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5+50;

struct node{
    ll mx;
    ll mn;
    ll sum;
};

int n,q;
ll arr[N<<2];
ll lazy[N<<2];
node tree[N<<2];

void pushdown(int rt,int l,int r){
    if(lazy[rt]){
        int mid = l+r>>1;
        int ls = rt<<1;
        int rs = rt<<1|1;

        tree[ls].mx = tree[rs].mx = tree[ls].mn = tree[rs].mn = lazy[rt];
        tree[ls].sum = (mid-l+1) * lazy[rt];
        tree[rs].sum = (r-mid) * lazy[rt];
        
        lazy[rt] = 0;
    }
}

void pushup(int rt){
    tree[rt].mx = tree[rt<<1].mx;
    tree[rt].mn = tree[rt<<1|1].mn;
    tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
}


void build(int l,int r,int rt){
    if(l==r){
        tree[rt].sum = tree[rt].mx = tree[rt].mn = arr[l];
    }else{
        build(l,l+r>>1,rt<<1);
        build(1+(l+r>>1),r,rt<<1|1);
        pushup(rt);
    }
}

void update(int l,int r,int rt,int ul,int ur,ll v){
    if(ul <= l && ur >= r){
        if(tree[rt].mn >= v)return;
        else if(tree[rt].mx <= v){
            tree[rt].mn=tree[rt].mx=v;
            tree[rt].sum=(r-l+1)*v;
            lazy[rt]=v;
            return;
        }else{
            int mid=l+r>>1;
            pushdown(rt,l,r);
            update(l,mid,rt<<1,l,mid,v);
            update(mid+1,r,rt<<1|1,mid+1,r,v);
            pushup(rt);
        }
    }else{
        int mid=l+r>>1;
        pushdown(rt,l,r);
        if(ul<=mid){
            update(l,mid,rt<<1,ul,ur,v);
        }
        if(ur>mid){
            update(mid+1,r,rt<<1|1,ul,ur,v);
        }
        pushup(rt);
    }
}

ll query_mx(int l,int r,int rt,int pos){ // 区间最大值实际上就在左端点.
    if(tree[rt].mx==tree[rt].mn){
        return tree[rt].mx;
    }else{
        pushdown(rt,l,r);
        int mid = l+r>>1;
        if(pos <= mid)return query_mx(l,mid,rt<<1,pos);
        else return query_mx(mid+1,r,rt<<1|1,pos);
    }
}


ll query_sum(int l,int r,int rt,int ql,int qr){
    if(ql <= l && qr >= r){
        return tree[rt].sum;
    }else{
        pushdown(rt,l,r);
        int mid = l+r>>1;
        ll ans = 0;
        if(ql <= mid)ans += query_sum(l,mid,rt<<1,ql,qr);
        if(qr > mid) ans += query_sum(mid+1,r,rt<<1|1,ql,qr);
        return ans;
    }
}


pii getans(int x,ll v){
    int l = x,r = n;
    int bg = -1,ed = -1;
    while(l <= r){
        int mid = l+r>>1;
        if(query_mx(1,n,1,mid) <= v){
            bg = mid;
            r = mid-1;
        }else{
            l = mid+1;
        }
    }

    if(bg==-1)return make_pair(-1,-1);

    l = bg;
    r = n;

    while(l <= r){
        int mid = l+r>>1;
        if(query_sum(1,n,1,bg,mid) <= v){
            ed = mid;
            l = mid+1;
        }else{
            r = mid-1;
        }
    }
    return make_pair(bg,ed);
}

int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++){scanf("%lld",&arr[i]);}
    build(1,n,1);
    int x,y; ll z;
    while(q--){
        scanf("%d%d%lld",&x,&y,&z);
        if(x==1){
            update(1,n,1,1,y,z);
        }else{
            int ans = 0;
            while(1){
                pii g = getans(y,z);
                if(g.first==-1)break;

                
                ans += g.second-g.first+1;
                y=g.second+1;
                z-=query_sum(1,n,1,g.first,g.second);

                if(y>n)break;
            }
            printf("%d\n",ans);
        }
    }

    // system("pause");
    return 0;
}

update 2020.11.18
刚刚听说这题貌似要用到吉如一线段树,维护最大值和次大值.
但是为什么我这个代码会wa呢?
即便复杂度不够优秀也不应该wa啊.
等我学完吉如一线段树再回来看看吧.

posted @ 2020-11-18 14:58  popozyl  阅读(253)  评论(0编辑  收藏  举报