• CF1405E Fixed Point Removal(线段树+二分)


    第一点可以想到的是,对于某个位置i上的数,他能不能被删除只和前面的数的能不能删除掉-(a[i]-i)的数有关。前提是他要a[i]-i小于0

    现在的问题是,因为他有很多询问,因为左区间的限定,我们对每个询问需要知道每个i对于当前左区间l-i之间能删除多少个数,这样我们才能知道对于当前区间这个点能不能删除。

    因此我们想到每个左区间的端点都是十分重要的,因此我们考虑维护一个线段树,每个点的意义都是以i为左区间能删除的数的大小。

    对于每个点,我们在线段树上二分查询到离他最近的能满足条件的位置,把点的贡献加到对应位置上,这样做是最优的。

    另外,这需要对询问排序,因为我们不能让后面的点对当前位置的答案产生错误的贡献

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=3e5+10;
    int n,q;
    int a[N];
    struct Q{
        int l,r;
        int id;
    }s[N];
    struct node{
        int l,r;
        int sum;
    }tr[N<<2];
    bool cmp(Q a,Q b){
        return a.r>b.r;
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,r,0};
        }
        else{
            tr[u]={l,r,0};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
        }
    }
    void modify(int u,int l,int x){
        if(tr[u].l==tr[u].r){
            tr[u].sum+=x;
            return ;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,x);
        else
            modify(u<<1|1,l,x);
        tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
    }
    int query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r){
            return tr[u].sum;
        }
        int mid=tr[u].l+tr[u].r>>1;
        int ans=0;
        if(l<=mid){
            ans+=query(u<<1,l,r);
        }
        if(r>mid)
            ans+=query(u<<1|1,l,r);
        return ans;
    }
    int ans[N];
    int get(int u,int l){
        if(tr[u].l==tr[u].r){
            return tr[u].l;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(tr[u<<1|1].sum>=l){
            return get(u<<1|1,l);
        }
        else{
            return get(u<<1,l-tr[u<<1|1].sum);
        }
    }
    int main(){
        cin>>n>>q;
        int i;
        for(i=1;i<=n;i++){
            cin>>a[i];
            a[i]-=i;
        }
        for(i=1;i<=q;i++){
            int x,y;
            cin>>x>>y;
            s[i]={x,y,i};
        }
        sort(s+1,s+1+q,cmp);
        int cur=1;
        int tot=0;
        build(1,1,n);
        for(i=1;i<=q;i++){
            while(cur<=n-s[i].r){
                if(a[cur]==0)
                    modify(1,cur,1),tot++;
                else if(a[cur]<0&&-a[cur]<=tot){
                    modify(1,get(1,-a[cur]),1);
                    tot++;
                }
                cur++;
            }
            ans[s[i].id]=query(1,s[i].l+1,n-s[i].r);
        }
        for(i=1;i<=q;i++)
            cout<<ans[i]<<endl;
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    2017微软骇客马拉松精彩大回Fun:不一样的Hacker,一Young的Cool
    老板这种生物:只看结果,不问过程
    小目标 | 分解任务,聪明人只设达得到的“小目标”
    本号讯 | 微软被 Forrester 评为销售服务自动化解决方案领导者
    IT圈网红,抢鲜围观
    云时代“非诚勿扰”
    安装conda后去除终端出现的(base)字样
    Ubuntu18.04 安装 Anaconda3
    高斯模糊
    准确率(Accuracy) 精确率(Precision) 与 召回率(Recall)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13761510.html
Copyright © 2020-2023  润新知