BZOJ4422[Cerc2015]Cow Confinement(扫描线+线段树)

很容易发现一个O(n2)DP,f[i][j]=f[i][j+1]+f[i+1][j]-f[i+1][j+1]。然后由于有栅栏,一些位置没办法走,然后就可以用类似差分的方法,f[i]表示当前行f[i+1]无法到达的花朵,然后对于每个点找到其下方第一个栅栏。分情况讨论,需要支持单点修改(出现花),区间标记覆盖(出现一个栅栏),以及区间归零(栅栏走了),当然还要区间查询(牛出现了),然后还要支持第一个障碍物的查询,不过这些用一个操作较多的线段树就可以跑过了,复杂度一个log可以“轻松”跑过。

#include<cstdio>
#include<algorithm>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N=2e6+7,M=1e6;
struct fence{int xl,xr,y,i;bool tp;}a[N<<1];
bool operator<(fence a,fence b){return a.y!=b.y?a.y>b.y:a.xl<b.xl;}
struct flower{int x,y;}b[N];
bool operator<(flower a,flower b){return a.y>b.y;}
struct cow{int x,y,i;}c[N];
bool operator<(cow a,cow b){return a.y>b.y;}
struct seg{int num;bool cov,cut;}tr[N<<2];
int n,m,val[N],ans[N];
void pushup(int rt)
{
    tr[rt].num=tr[rt<<1].num+tr[rt<<1|1].num;
    tr[rt].cut=tr[rt<<1].cut|tr[rt<<1|1].cut;
}
void modify(int rt){tr[rt].cov=1,tr[rt].num=0;}
void pushdown(int rt){if(tr[rt].cov)modify(rt<<1),modify(rt<<1|1),tr[rt].cov=0;}
void add(int k,int v,int l,int r,int rt)
{
    tr[rt].num+=v;
    if(l==r)return;
    pushdown(rt);
    int mid=l+r>>1;
    if(k<=mid)add(k,v,lson);else add(k,v,rson);
    pushup(rt);
}
void cover(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R){modify(rt);return;}
    pushdown(rt);
    int mid=l+r>>1;
    if(L<=mid)cover(L,R,lson);
    if(R>mid)cover(L,R,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)return tr[rt].num;
    pushdown(rt);
    int mid=l+r>>1,ret=0;
    if(L<=mid)ret+=query(L,R,lson);
    if(R>mid)ret+=query(L,R,rson);
    return ret;
}
void update(int k,int l,int r,int rt)
{
    if(l==r){tr[rt].cut^=1;return;}
    pushdown(rt);
    int mid=l+r>>1;
    if(k<=mid)update(k,lson);else update(k,rson);
    pushup(rt);
}
int getnxt(int L,int l,int r,int rt)
{
    if(l>=L)
    {
        if(tr[rt].cut)
        {
            while(l!=r)
            if(tr[rt<<1].cut)rt<<=1,r=l+r>>1;
            else rt=rt<<1|1,l=(l+r>>1)+1;
            return l;
        }
        return 0;
    }
    int tmp,mid=l+r>>1;
    pushdown(rt);
    if(L<=mid&&(tmp=getnxt(L,lson)))return tmp;
    return getnxt(L,rson);
}
int main()
{
    int f;scanf("%d",&f);
    for(int i=0,x1,y1,x2,y2;i<f;i++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        a[i<<1]=(fence){x1,x2,y1-1,i,0};
        a[i<<1|1]=(fence){x1,x2,y2,i,1};
    }
    sort(a,a+(f<<1));
    scanf("%d",&m);
    for(int i=1;i<=m;i++)scanf("%d%d",&b[i].x,&b[i].y);
    sort(b+1,b+m+1);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&c[i].x,&c[i].y),c[i].i=i;
    sort(c+1,c+n+1);
    f=0;
    update(M,1,M,1);
    for(int i=M,p=1,q=1;i;i--)
    {
        int sum,cut;
        while(a[f].y==i)
        {
            if(!a[f].tp)
            {
                cover(a[f].xl,a[f].xr,1,M,1);
                if(a[f].xl!=1)add(a[f].xl-1,-val[a[f].i],1,M,1);
                if(a[f].xl!=1)update(a[f].xl-1,1,M,1);
                if(a[f].xr!=M)update(a[f].xr,1,M,1);
            }
            else{
                cut=getnxt(a[f].xr,1,M,1),sum=query(a[f].xl,a[f].xr,1,M,1);
                val[a[f].i]=query(a[f].xr+1,cut,1,M,1);
                cover(a[f].xl,a[f].xr,1,M,1);
                if(a[f].xl>1)add(a[f].xl-1,sum+val[a[f].i],1,M,1);
                if(a[f].xl!=1)update(a[f].xl-1,1,M,1);
                if(a[f].xr!=M)update(a[f].xr,1,M,1);
            }
            f++;
        }
        while(b[p].y==i)add(b[p].x,1,1,M,1),++p;
        while(c[q].y==i)cut=getnxt(c[q].x,1,M,1),ans[c[q].i]=query(c[q].x,cut,1,M,1),++q;
    }
    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
}
View Code

 

posted @ 2019-05-31 08:07  hfctf0210  阅读(288)  评论(1编辑  收藏  举报