zoukankan      html  css  js  c++  java
  • P6007 [USACO20JAN]Springboards G

    本题解仅用与作者加深算法理解,也欢迎大家的阅读

    做题背景

    原本关于二维的点的 (dp) 问题一直都没有什么想法,昨天晚上再做一道 (cdq) 的题目的时候被同学询问了这道题,发现可以用二维偏序使用的第一关键字排序,第二关键字用数据结构维护的方法来做,今天就把他切了。

    题意

    你需要从点 ((0,0)) 走到点 ((n,n)) ,且只能向右或向上走。同时给你 (p) 个点对 ((x_1,y_1),(x_2,y_2)) ,满足 (x_1 leq x_2)(y_1 leq y_2) 。如果你在中间走到了一个点对的第一个点,你可以立即达到第二点(不计算距离),问你行走的最小距离是多少。

    题解

    我们联想到用解决二维偏序的方法来做。

    我们先根据点对的 (x_1) (第一关键词)和 (y_1) (第二关键词)来排序,这样的话我们的 (dp) 肯定是没有后效性的,然后易得,每一个点对的答案肯定得是从 (x_1) 前面的 (y_2) 比它小的点转移过来的,同时每个点可以更新的点是满足 (x_2) 后面的 (y_1) 比他大的点,这个东西是可以用树状数组来维护的。

    (P.S.)(y_1) 作为第二关键词是因为会出现一些比较奇怪的点对,比如点对 ((0,0),(0,1)) 和点对 ((0,2),(0,3)) ,此时仅根据 (x_1) 排序肯定是不行的,可以再加一个第二关键词 (y_1)

    然后我们又发现,每一个点更新的顺序并不等于我们排序后的顺序(排序是根据 (x_1) ,更新是根据 (x_2) ),所以我们可以考虑用一个 (set) 来维护一下更新的时间顺序,到了相应的 (x) 轴位置再更新相应的点。

    然后细节处理好就可以 (AC) 了,不要忘记离散化。

    以上。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define IT set<pair<int,int> >::iterator
    const int N=1e5+5;
    int n,maxn;
    struct Board{int x1,y1,x2,y2,data;}s[N];
    bool cmp(Board a,Board b)
    {
    	if(a.x1!=b.x1)
    	return a.x1<b.x1;
    	return a.y1<b.y2;
    };
    map<int,int> mpx,mpy;
    int ux[N<<1],sizex,uy[N<<1],sizey;
    set<pair<int,int> > st;
    struct TreeArray
    {
    	int s[N<<1];
    	int lowbit(int x){return x&(-x);}
    	void updata(int k,int x){for(;k<(N<<1);k+=lowbit(k))s[k]=min(s[k],x);}
    	int query(int k){int res=1e18+7;for(;k;k-=lowbit(k))res=min(res,s[k]);return res;}
    }t;
    signed main()
    {
    	cin>>maxn>>n;;
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%lld%lld%lld%lld",&s[i].x1,&s[i].y1,&s[i].x2,&s[i].y2);
    		ux[++sizex]=s[i].x1,ux[++sizex]=s[i].x2;
    		uy[++sizey]=s[i].y1,uy[++sizey]=s[i].y2;
    	}
    	sort(s+1,s+1+n,cmp);
    	ux[++sizex]=0,ux[++sizex]=maxn;
    	uy[++sizey]=0,uy[++sizey]=maxn;
    	sort(ux+1,ux+1+sizex);
    	sort(uy+1,uy+1+sizey);
    	sizex=unique(ux+1,ux+1+sizex)-ux-1;
    	sizey=unique(uy+1,uy+1+sizey)-uy-1;
    	for(int i=1;i<=sizex;++i) mpx[ux[i]]=i;
    	for(int i=1;i<=sizey;++i) mpy[uy[i]]=i;
    	for(int i=1;i<=n;++i)
    	{
    		int tmp=mpx[s[i].x1];
    		for(IT j=st.begin();j!=st.end()&&j->first<=tmp;++j)
    		t.updata(mpy[s[j->second].y2],s[j->second].data-s[j->second].x2-s[j->second].y2);
    		while(!st.empty()&&st.begin()->first<=tmp) st.erase(st.begin());
    		s[i].data=t.query(mpy[s[i].y1])+s[i].x1+s[i].y1;
    		st.insert(make_pair(mpx[s[i].x2],i));
    		// printf("%d %d %d
    ",s[i].x1,s[i].y1,s[i].data);
    	}
    	int tmp=mpx[maxn];
    	for(IT j=st.begin();j!=st.end()&&j->first<=tmp;++j)
    	t.updata(mpy[s[j->second].y2],s[j->second].data-s[j->second].x2-s[j->second].y2);
    	printf("%lld
    ",t.query(mpy[maxn])+maxn+maxn);
    	return 0;
    }
    
  • 相关阅读:
    zindex在IE中的迷惑(一)
    IE “+” CSS Hack研究
    display:inlineblock的深入理解
    CSS解决未知高度垂直居中
    zindex在IE中的迷惑(二)
    三角的一个特殊做法
    图片垂直居中的使用技巧
    简单form标准化实例(一):整体布局
    简单form标准化实例(二):语义结构
    CSS定义通用透明效果
  • 原文地址:https://www.cnblogs.com/Point-King/p/13639066.html
Copyright © 2011-2022 走看看