zoukankan      html  css  js  c++  java
  • 【洛谷4348】[CERC2015] Cow Confinement(扫描线+线段树优化DP)

    点此看题面

    • 一张(10^6 imes10^6)的网格图上有(f)个无交的矩形围栏(围栏在格边上)。
    • 格子中有(n)头牛和(m)朵花,牛只能向右或向下走且不能越过围栏,求每头牛能到达的花的数量。
    • (n,m,fle2 imes10^5)

    暴力(DP)

    考虑(DP),设(f_{i,j})表示((i,j))中的牛能到达多少朵花。

    如果它右方没有围栏,就可以从(f_{i,j+1})转移;如果它下方没有围栏,就可以从(f_{i+1,j})转移。

    暴力转移肯定(T)飞,需要优化。

    扫描线+线段树优化(DP)

    我们可以利用扫描线,从后往前枚举每一列,只要知道这一列上的所有围栏,就知道能否从(f_{i,j+1})转移了。

    而要知道能否从下方转移,可以开个(set)维护一下所有下方有围栏的行,相当于一列被划分成了若干段,同一段中是可以从(f_{i+1,j})转移的。

    考虑用一棵线段树来维护一列的所有(DP)值,从右转移是非常简单的:先全部继承,然后把有围栏的部分清零。

    而从下转移就非常困难了,因此我们决定放弃转移,直接用(f_{i,j})记录从((i,j))开始往右走的答案,询问时只要查询从询问点开始向下一整段的(f_{i,j})之和。

    但真的只往右走肯定也是不行的,有些时候下方存在障碍格,最迟需要从这一行出发向下才能走到,我们把这部分的格子数也计入这一行的答案之中。

    具体地,对于一个围栏((x,y)-(u,v)),我们在进入它和离开它的时候分别需要下述操作:

    • (v)进入:段被划开,产生(x-1)(u)两个新的划分点。对于第(x-1)行,原先段中(x)及其下方的格子需要从第(x-1)行出发到达,因此把这一部分的答案计入(f_{x-1,j})
    • (y-1)离开:段被重新合并。对于第(x-1)行,进入围栏之前(xsim u)右边的格子依旧需要从第(x-1)行出发到达,而(y+1)及其下方的格子可以第(y+1)行及其下方的格子出发到达,需要把这一部分从(f_{x-1,j})中减去(可以在进入时记录)。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000000
    using namespace std;
    int n,g[N+5],ans[N+5];set<int> p;
    struct OP
    {
    	int op,x,y,ty;I OP(CI i=0,CI a=0,CI b=0,CI c=0):op(i),x(a),y(b),ty(c){}
    	I bool operator < (Con OP& o) Con {return op^o.op?op<o.op:x<o.x;}
    };vector<OP> q[N+5];vector<OP>::iterator it;
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[30],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    class SegmentTree
    {
    	private:
    		#define PT CI l=1,CI r=N+1,CI rt=1
    		#define LT l,mid,rt<<1
    		#define RT mid+1,r,rt<<1|1
    		#define PU(x) (V[x]=V[x<<1]+V[x<<1|1])
    		#define PD(x) (F[x]&&(D(x<<1),D(x<<1|1),F[x]=0))
    		#define D(x) (V[x]=0,F[x]=1)
    		int V[N<<2],F[N<<2];
    	public:
    		I void U(CI x,CI v,PT)//单点加法
    		{
    			if(l==r) return (void)(V[rt]+=v);RI mid=l+r>>1;PD(rt);
    			x<=mid?U(x,v,LT):U(x,v,RT),PU(rt);
    		}
    		I void E(CI L,CI R,PT)//区间清零
    		{
    			if(L<=l&&r<=R) return (void)D(rt);RI mid=l+r>>1;PD(rt);
    			L<=mid&&(E(L,R,LT),0),R>mid&&(E(L,R,RT),0),PU(rt);
    		}
    		I int Q(CI L,CI R,PT)//区间求和
    		{
    			if(L<=l&&r<=R) return V[rt];RI mid=l+r>>1;PD(rt);
    			return (L<=mid?Q(L,R,LT):0)+(R>mid?Q(L,R,RT):0);
    		}
    }S;
    int main()
    {
    	RI i,x,y,u,v;p.insert(N+1);
    	for(read(n);n;--n) read(x),read(y),read(u),read(v),q[y-1].push_back(OP(1,x,u,-1)),q[v].push_back(OP(1,x,u,1));//把围栏拆成两部分
    	for(read(n);n;--n) read(x),read(y),q[y].push_back(OP(2,x));//花
    	for(read(n),i=1;i<=n;++i) read(x),read(y),q[y].push_back(OP(3,x,i));//牛
    	for(i=N;i;--i) for(sort(q[i].begin(),q[i].end()),it=q[i].begin();it!=q[i].end();++it) switch(x=it->x,y=it->y,it->op)//扫描线从后往前枚举每一列
    	{
    		#define R(x) *p.lower_bound(x)//x所在段的右端点
    		case 1:if(!~it->ty) x^1&&(p.erase(S.U(x-1,-g[x-1]),p.find(x-1)),0),p.erase(p.find(y)),S.E(x,y);//离开时x-1减去y+1及其后的贡献
    			else x^1&&(S.U(x-1,S.Q(x,y)+(g[x-1]=S.Q(y+1,R(y)))),p.insert(x-1),0),p.insert(y),S.E(x,y);break;//进入时x-1加上x及其后的贡献(记录y+1及其后的贡献)
    		case 2:S.U(x,1);break;case 3:ans[y]=S.Q(x,R(x));break;//单点修改;询问所在段后缀和
    	}
    	for(i=1;i<=n;++i) writeln(ans[i]);return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    做报表,写Sql语句的一点收获
    ORACLE PL/SQ入门
    用Visual C#实现P2P应用程序
    css资源网站收集推荐
    Ubuntu 蓝牙全攻略
    Asp.Net细节性问题技巧精萃
    Asp.net Request获取服务器变量的方法
    如何将flash插入到Excel文件中
    XP远程桌面连接强制登录
    flash研究(三)——Falsh与JavaScript交互
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu4348.html
Copyright © 2011-2022 走看看