zoukankan      html  css  js  c++  java
  • [BZOJ4422] [Cerc2015]Cow Confinement

    [BZOJ4422] [Cerc2015]Cow Confinement

    Description

    一个106行106列的网格图,上面有一些牛、花和一些矩形围栏,围栏在格子的边界上,牛和花在格子里,牛只能向下或向右走,牛也不能穿过围栏和地图边界,求每头牛它能到达的花的数量。注意栅栏不会相交

    Input

    第一行一个数f表示矩形围栏的数量。接下来f行,每行四个数x1,y1,x2,y2,表示(x1,y1)在围栏内部矩形的左上角,(x2,y2)在右下角。接下来一行一个数m表示花的数量。接下来m行每行两个数x,y,表示在(x,y)处有一朵花。接下来一行一个数n表示牛的数量。接下来n行每行两个数x,y,表示在(x,y)处有一头牛。

    Output

    总共n行,每行一个数ans,第i个数表示第i头牛能到ans个花。

    Sample Input

    4
    2 2 8 4
    1 9 4 10
    6 7 9 9
    3 3 7 3
    9
    3 4
    8 4
    11 5
    10 7
    10 8
    9 8
    2 8
    4 11
    9 11
    8
    1 1
    5 10
    6 9
    3 7
    7 1
    4 2
    7 5
    3 3

    Sample Output

    5
    1
    0
    1
    3
    1
    3
    0

    HINT

    0<=f<=200000
    0<=m<=200000
    1<=n<=200000

    试题分析

    神题毒瘤题二合一系列
    毕竟是Cerc2015的防AK题
    我们首先可以列出一个很暴力的转移方程:(f_{i,j})表示从((i,j))出发可以到达多少个花。
    然后讨论许许多多的情况并转移。复杂度:(O((n+m+f)^2))
    这种东西二维数点+容斥做不了,可以被特殊数据卡成时空复杂度均(O(qn))
    那么就是数据结构优化(dp)喽,但单看转移方程并没有办法优化。
    通常在这种情况下我们有两类手段:

    • 差分
    • 前缀和优化
      这怎么看也不想前缀和优化啊,差分显然更靠谱。
      由于是右下角,所以注意扫描线从右到左扫描。
      怎么差分呢?我们不妨设(g{i,j}=f_{i,j}-f_{i+1,j}),也就是当前行i比它下面一个格子(i+1,j)可以多多少花。

    那么更形象一点来说就是(i,j)可以走到多少从(i+1,j)走不到的花。
    这样的话遇见一朵花就单点+1即可。
    如果我们遇到了一个新的区间怎么办呢?
    可以发现,最左上角的蓝色格子以及上面(假设还有格子)的若干格子都还可以走到红色部分,而新增矩形下方的从来就不可以走到。
    所以((x_l-1,y))要加上红色部分+黑色部分(从黑格子到下一个框)的区间和,++因为当询问矩形上面的点时,我们需要走到右下去++,并且把黄色区间置零。
    注意我们是从上往下扫的,所以如果黄色区间中有花就还可以加上。
    删除一个区间怎么办呢?
    首先还是区间置0(竖着的浅绿色区间),因为两两之间都一样了。
    还要考虑左上角的格子(5,6),这个格子照样有向右走的“特权”,所以在这一点上不用变动。
    但是这里有一个需要注意的地方:注意黑色格子,这个格子到最下面(下一个框)会被当前点向右走再向下走计算一遍,并且会被向下走再向右走计算一遍,所以要减一遍,我们可以在区间加入的时候把这个答案先询问好。
    查询的话显然就是从奶牛到它下面的第一个栅栏的区间和。

    一定要注意在线段树中加入不合法特判。

    咕咕咕代码在线修补完成

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    //#include<ctime>
    //#include<cmath>
    //#include<queue>
    #include<set>
    
    using namespace std;
    #define LL long long
    #define rr register
    
    namespace IO
    {
        const int S=(1<<20)+5;
        //Input Correlation
        char buf[S],*H,*T;
        inline char Get()
        {
            if(H==T) T=(H=buf)+fread(buf,1,S,stdin);
            if(H==T) return -1;return *H++;
        }
        inline int read()
        {
            rr int x=0;rr char c=Get();
            while(!isdigit(c)) c=Get();
            while(isdigit(c)) x=x*10+c-'0',c=Get();
            return x;
        }
        inline void reads(char *s)
        {
            rr char c=Get();rr int tot=0;
            while(c<'a'||c>'z') c=Get();
            while(c>='a'&&c<='z') s[++tot]=c,c=Get();
            s[++tot]='';
        }
        //Output Correlation
        char obuf[S],*oS=obuf,*oT=oS+S-1,c,qu[55];int qr;
        inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
        inline void putc(char x){*oS++ =x;if(oS==oT) flush();}
        template <class I>inline void print(I x)
        {
            if(!x) putc('0');
            if(x<0) putc('-'),x=-x;
            while(x) qu[++qr]=x%10+'0',x/=10;
            while(qr) putc(qu[qr--]);
        }
    }
    using namespace IO;
    const int INF = 2147483600;
    const int MAXN = 200010;
    const int Y = 1000000;
    
    struct data{
    	int y,l,r,opr,x,id;
    }q[MAXN<<3];
    int N,M,C;
    
    bool cmp(data a,data b){
    	if(a.y!=b.y) return a.y>b.y;
    	if(a.opr==1) return 0;
    	if(b.opr==1) return 1;
    	if(a.x!=b.x) return a.x<b.x;
    	return a.opr>b.opr;
    }
    multiset<int> s;
    multiset<int>::iterator it,it2; 
    int ret[MAXN<<1];
    bool rev[Y*4+10]; int sum[Y*4+10];
    int tot=0;
    inline int Down(int x){
    	it=s.upper_bound(x); return (*it)-1;
    }
    inline void tage_lazy(int rt){
    	if(rev[rt]) {
    		sum[rt<<1]=sum[rt<<1|1]=0;
    		rev[rt]=0; rev[rt<<1]=rev[rt<<1|1]=1;
    	} return ;
    }
    inline void Init(int rt,int l,int r,int L,int R){
    	if(L>R||!L||R>Y) return ;
    	if(L<=l&&R>=r){rev[rt]=1; sum[rt]=0; return ;}
    	int mid=(l+r)>>1; tage_lazy(rt);
    	if(L<=mid) Init(rt<<1,l,mid,L,R);
    	if(R>mid) Init(rt<<1|1,mid+1,r,L,R);
    	sum[rt]=sum[rt<<1]+sum[rt<<1|1]; return ;
    }
    inline void Add(int rt,int l,int r,int k,int x){
    	if(!k||k>Y) return ;
    	if(l==r){sum[rt]+=x; return ;} tage_lazy(rt);
    	int mid=(l+r)>>1; if(k<=mid) Add(rt<<1,l,mid,k,x);
    	else Add(rt<<1|1,mid+1,r,k,x); sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    inline int Query(int rt,int l,int r,int L,int R){
    	if(L>R||!L||R>Y) return 0;
    	if(L<=l&&R>=r) return sum[rt]; tage_lazy(rt);
    	int mid=(l+r)>>1,ans=0; if(L<=mid) ans+=Query(rt<<1,l,mid,L,R);
    	if(R>mid) ans+=Query(rt<<1|1,mid+1,r,L,R);
    	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    	return ans;
    } 
    
    int ans[MAXN+1];
    
    int main(){
    	N=read();
    	for(int i=1;i<=N;i++){
    		int x1=read(),y1=read(),x2=read(),y2=read();
    		q[++tot].y=y2; q[tot].x=x1; q[tot].l=x1; q[tot].r=x2; q[tot].opr=3; q[tot].id=i;
    		q[++tot].y=y1-1; q[tot].x=x1; q[tot].l=x1; q[tot].r=x2; q[tot].opr=4; q[tot].id=i;
    	} 
    	M=read();
    	for(int i=1;i<=M;i++){
    		q[++tot].x=read(); q[tot].y=read(); q[tot].opr=2;
    	}
    	C=read();
    	for(int i=1;i<=C;i++){
    		q[++tot].x=read(); q[tot].y=read(); q[tot].opr=1;
    		q[tot].id=i;
    	} sort(q+1,q+tot+1,cmp);
    	int j=1; s.insert(0); s.insert(Y+1);
    	for(int i=Y;i>=1;i--){
    		while(j<=tot&&q[j].y==i){
    			if(q[j].opr==4){
    				Init(1,1,Y,q[j].l,q[j].r);
    				Add(1,1,Y,q[j].l-1,-ret[q[j].id]);
    				s.erase(s.find(q[j].l)); s.erase(s.find(q[j].r+1));
    			} else if(q[j].opr==3){
    				int pos=Down(q[j].r+1),su=0;
    				ret[q[j].id]=Query(1,1,Y,q[j].r+1,pos);
    				su=Query(1,1,Y,q[j].l,q[j].r);
    				Add(1,1,Y,q[j].l-1,su+ret[q[j].id]);
    				Init(1,1,Y,q[j].l,q[j].r); 
    				s.insert(q[j].l); s.insert(q[j].r+1);
    			} else if(q[j].opr==2){
    				Add(1,1,Y,q[j].x,1);
    			} else{
    				int pos=Down(q[j].x); it=s.upper_bound(q[j].x);
    				ans[q[j].id]=Query(1,1,Y,q[j].x,pos);
    			}
    			++j;
    		}
    	} for(int i=1;i<=C;i++){
    		printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    简单的两个字“谢谢”,会让我坚持我的写作,我也要谢谢你们
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    远程桌面无法登录windows server 2003服务器
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    远程桌面无法登录windows server 2003服务器
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    关于ajax 和josn
  • 原文地址:https://www.cnblogs.com/wxjor/p/9643234.html
Copyright © 2011-2022 走看看