• X day4


    题目

    官方题解

     T1:

    单调栈,单调队列因为认为考场上会写崩所以写了一个十分暴力的方法(线段树)

    然后做一做区间覆盖即可

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define int long long
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int k[800001],n,a[800001],tmp[800001],res[800001],ans[800001];
    void pushdown(int k,int l,int r){
        if(res[k]==-1) return;
        ans[k<<1]=res[k];
        ans[k<<1|1]=res[k];
        res[k<<1]=res[k<<1|1]=res[k];
        res[k]=-1;
        return;
    }
    int query1(int k,int l,int r,int x,int y){
        if(x>y) return 0;
        if(x<=l&&r<=y) return ans[k];
        int mid=l+r>>1,maxn=0;
        pushdown(k,l,r);
        if(x<=mid) maxn=max(maxn,query1(k<<1,l,mid,x,y));
        if(mid<y) maxn=max(maxn,query1(k<<1|1,mid+1,r,x,y));
        ans[k]=max(ans[k<<1],ans[k<<1|1]);
        return maxn;
    }
    int query(int k,int l,int r,int x,int y){
        
        if(x>y) return 2<<30-1;
        if(x<=l&&r<=y) {
            return ans[k];
        }
        pushdown(k,l,r);
        int mid=l+r>>1,minn=2<<30-1;
        if(x<=mid) minn=min(minn,query(k<<1,l,mid,x,y));
        if(mid<y) minn=min(minn,query(k<<1|1,mid+1,r,x,y));
        ans[k]=min(ans[k<<1],ans[k<<1|1]);
        return minn;
    }
    void update1(int k,int l,int r,int x,int y,int pos){
        if(x>y) return;
        if(x<=l&&r<=y){ans[k]=res[k]=pos;return;}
        pushdown(k,l,r);
        int mid=l+r>>1;
        if(x<=mid) update1(k<<1,l,mid,x,y,pos);
        if(mid<y) update1(k<<1|1,mid+1,r,x,y,pos);
        ans[k]=max(ans[k<<1],ans[k<<1|1]);
        return;
    }
    void update(int k,int l,int r,int x,int y,int pos){
        if(x>y) return;
        if(x<=l&&r<=y){ans[k]=res[k]=pos;return;}
        pushdown(k,l,r);
        int mid=l+r>>1;
        if(x<=mid) update(k<<1,l,mid,x,y,pos);
        if(mid<y) update(k<<1|1,mid+1,r,x,y,pos);
        ans[k]=min(ans[k<<1],ans[k<<1|1]);
        return;
    }
    int h[50001],anss[50001],maxv;
    signed main(){
        memset(res,-1,sizeof(res));
        n=read();
        for(int i=1;i<=n;i++) k[i]=tmp[i]=a[i]=read(),h[i]=read();
        sort(tmp+1,tmp+n+1);
        for(int i=1;i<=n;i++) a[i]=lower_bound(tmp+1,tmp+n+1,a[i])-tmp;
        for(int i=1;i<=n;i++){
            int t1=query1(1,1,n,a[i]+1,n);
            anss[t1]+=h[i];
            update1(1,1,n,1,a[i],i);
        }
        memset(res,-1,sizeof(res));
        memset(ans,127/3,sizeof(ans));
        for(int i=n;i>=1;i--){
            int t1=query(1,1,n,a[i]+1,n);
            if(t1>=1&&t1<=n) anss[t1]+=h[i];
            update(1,1,n,1,a[i],i);
        }
        for(int i=1;i<=n;i++)maxv=max(maxv,anss[i]);
        cout<<maxv;
    }
    View Code

    T2:

    易发现答案是具有单调性的,所以二分判一判即可

    时间复杂度:$O(n^2 log n)$

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int c,n;
    int x[1001],y[1001],minn=2<<30-1,xp[1001];
    struct node{
        int x,y;
    }st[1001];
    bool CHECK(int l,int r,int w){
        if(r-l+1<c) return 0;
        int cnt=0;
        int yp[1001];
        memset(yp,0,sizeof(yp));
        for(int i=l;i<=r;i++) yp[++yp[0]]=st[i].y;
        sort(yp+1,yp+yp[0]+1);
        for(int i=c;i<=yp[0];i++){
            if(yp[i]-yp[i-c+1]<=w) {
                return 1;
            }
        }
        return 0;
    }
    bool cmp(node x1,node x2){return x1.x<x2.x;}
    bool check(int xx){
        int l=1;
        for(int i=1;i<=n;i++) st[i].x=x[i],st[i].y=y[i];
        sort(st+1,st+n+1,cmp);
        for(int r=1;r<=n;r++){
            if(st[r].x-st[l].x>xx){
                if(CHECK(l,r-1,xx)) {
                    return 1;
                }
                while(st[r].x-st[l].x>xx) l++;
            }
        }
        if(CHECK(l,n,xx)) return 1;
        return 0;
    }
    int main(){
        c=read(),n=read();
        for(int i=1;i<=n;i++) x[i]=read(),y[i]=read();
        int l=0,r=10001;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid)) minn=min(minn,mid),r=mid-1;
            else l=mid+1;
        }
        cout<<minn+1;
    }
    View Code
  • 相关阅读:
    2020/5/8
    2020/5/8
    2020/5/6
    2020/4/30
    2020/4/29
    2020/4/28
    2020/4/27
    KMP算法详解
    博客搬家声明
    洛谷P2831 NOIP2016 愤怒的小鸟
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/9920952.html
Copyright © 2020-2023  润新知