zoukankan      html  css  js  c++  java
  • bzoj4662: Snow

    调了一早上80pt不知道那里错了。。。结果发现我看错题意了。。。一个清洁工扫的是区间而不是点。。。

    先离散化

    首先对于一个人它扫了地,他影响的其他人是一个区间

    而且每个区间都只会被扫一次,所以我们可以暴力枚举

    那么算法的架构已经出来了:线段树维护清洁工清理区间长度的最小值,然后每次选出一个清洁工,就把它扫的区间枚举一次,修改会被影响的其他清洁工

    并查集瞎维护一下就可以了。。。今年NOIP才考

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    
    #define mid (ql+qr)/2
    #define lc now<<1
    #define rc now<<1|1
    using namespace std;
    typedef pair<int,int> pa;
    const int _=100;
    const int maxn=3*1e5+_;
    const int fbin=(1<<19)+_;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void write(int x)
    {
        if(x<0)putchar('-');
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    
    struct node{int l,r,id;}p[maxn];
    bool cmp(node n1,node n2){return n1.l<n2.l;}
    int lslen,ls[maxn*4],sd[maxn*4];
    
    //----------------------------------def--------------------------------------------------
    
    struct trnode
    {
        int mn,id,la;
    }tr[fbin*2];int z;
    void update(int now)
    {
        if(tr[lc].mn<0){tr[now].mn=tr[rc].mn,tr[now].id=tr[rc].id;return ;}
        if(tr[rc].mn<0){tr[now].mn=tr[lc].mn,tr[now].id=tr[lc].id;return ;}
        
        if((tr[lc].mn<tr[rc].mn||(tr[lc].mn==tr[rc].mn&&tr[lc].id<tr[rc].id)))
            tr[now].mn=tr[lc].mn,tr[now].id=tr[lc].id;
        else
            tr[now].mn=tr[rc].mn,tr[now].id=tr[rc].id;
    }
    void pushdown(int now)
    {
        if(tr[now].la==0)return ;
        if(tr[lc].mn!=-1)tr[lc].mn+=tr[now].la,tr[lc].la+=tr[now].la;
        if(tr[rc].mn!=-1)tr[rc].mn+=tr[now].la,tr[rc].la+=tr[now].la;
        tr[now].la=0;
    }
    //~~~~~~~~in~~~~~~~~~~~
    
    void bt(int now,int ql,int qr)
    {    
        if(ql==qr){ tr[now].mn=sd[p[ql].r]-sd[p[ql].l],tr[now].id=++z; return ; }
        else{ bt(lc,ql,mid),bt(rc,mid+1,qr); update(now); }
    }
    void change(int now,int ql,int qr,int l,int r,int d)
    {
        if(ql==l&&qr==r){tr[now].mn+=d,tr[now].la+=d;return ;}
        pushdown(now);
             if(r<=mid)  change(lc,ql,mid,l,r,d);
        else if(mid+1<=l)change(rc,mid+1,qr,l,r,d);
        else change(lc,ql,mid,l,mid,d),change(rc,mid+1,qr,mid+1,r,d);
        update(now);
    }
    int findmn(int now,int ql,int qr,int p)
    {
        if(ql==qr){return tr[now].mn;}
        pushdown(now);
        if(p<=mid)return findmn(lc,ql,mid,p);
        else return findmn(rc,mid+1,qr,p);
    }    
    //~~~~~~~~~~~out~~~~~~~~~~~~~~~
    
    //-----------------------------------seg----------------------------------------------
    
    int R[maxn*4];
    int findR(int x)
    {
        if(R[x]==x)return x;
        R[x]=findR(R[x]);return R[x];
    }
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int T,n;
        T=read(),n=read();
        for(int i=1;i<=n;i++)
            p[i].l=read(),p[i].r=read(),p[i].id=i;
        sort(p+1,p+n+1,cmp);
        
        for(int i=1;i<=n;i++)
            ls[++lslen]=p[i].l,ls[++lslen]=p[i].r;
        sort(ls+1,ls+lslen+1);
        lslen=unique(ls+1,ls+lslen+1)-ls-1;
        for(int i=2;i<=lslen;i++)
            sd[i]=sd[i-1]+ls[i]-ls[i-1];
        for(int i=1;i<=n;i++)
        {
            p[i].l=lower_bound(ls+1,ls+lslen+1,p[i].l)-ls,
            p[i].r=lower_bound(ls+1,ls+lslen+1,p[i].r)-ls;
        }
        
        //-------------------------LSH-------------------------
        
        bt(1,1,n);
        for(int i=0;i<=lslen+1;i++)R[i]=i;
        int x;
        for(int t=1;t<=n;t++)
        {
            x=tr[1].id;
            write(p[x].id);puts("");
            
            int l,r,st,ed;
            for(int k=findR(p[x].l+1);k<=p[x].r;R[k]=findR(k+1),k=R[k])
            {
                l=1,r=n,st=n+1;
                while(l<=r)
                {
                    int m=(l+r)/2;
                    if(k<=p[m].r)r=m-1,st=m;
                    else l=m+1;
                }
                l=1,r=n,ed=0;
                while(l<=r)
                {
                    int m=(l+r)/2;
                    if(p[m].l<k)l=m+1,ed=m;
                    else r=m-1;
                }
                
    
                if(st<=ed)
                    change(1,1,n,st,ed,sd[k-1]-sd[k]);
            }
            change(1,1,n,x,x,-1);
        }
            
        return 0;
    }
  • 相关阅读:
    工厂模式--工厂方法模式(Factory Method Pattern)
    工厂模式--简单工厂模式( Simple Factory Pattern )
    blog2.0--Springboot添加redis缓存(注解方式)
    blog2.0--JSR303参数校验+全局异常处理器
    高并发秒杀——SpringBoot集成redis
    SpringBoot报错HHH000206: hibernate.properties not found
    blog2.0--保存博客文章到本地磁盘
    Swagger注解 传参
    设计模式--单例模式
    跳表
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10341860.html
Copyright © 2011-2022 走看看