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;
}

 

posted @ 2019-01-31 14:32  AKCqhzdy  阅读(166)  评论(0编辑  收藏  举报