很容易发现一个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 ",ans[i]); }