http://acm.hdu.edu.cn/showproblem.php?pid=6669
题意:有n个任务要依次完成,每个任务都是:只要站在
[
L
i
,
R
i
]
[L_i,R_i]
[Li,Ri]区间,就完成了。起点任选,每次走1步或者2步,求最少走几步。
思路:首先读好题,注意依次,不能打乱顺序。首先我们根据第一个与前i个区间不相交的区间在前i个的并区间的右还是左,就可以确定起点,然后依次走就行了,有一个问题是,如果走的步数是奇数,并且再下一个区间还是同方向,可能走到这个区间的下一格更好,这样的话,怎么判断呢?如果用循环,代码写的又长又乱,一直wa。遂开始时预处理好,一直并区间,形成cnt个相邻绝对不相交的区间,然后就好判断了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1000+100;
const int maxl=1000000+100;
const int INF=0x3f3f3f3f;
int T,n,ans,cnt;
struct seg{
int l,r;
}a[maxn],b[maxn];
int dist(int pos,int p)
{
return min(abs(b[pos].l-p),abs(b[pos].r-p));
}
void init()
{
cin>>n;
ans=0;
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].l,&a[i].r);
cnt=1;
b[1]=a[1];
for(int i=2;i<=n;i++)
{
if(a[i].l>b[cnt].r || a[i].r<b[cnt].l)b[++cnt]=a[i];
else
{
b[cnt].l=max(b[cnt].l,a[i].l);
b[cnt].r=min(b[cnt].r,a[i].r);
}
}
}
void solve()
{
if(cnt==1)return;
int p;
if(b[2].l>b[1].r)p=b[1].r;
else p=b[1].l;
for(int i=2;i<=cnt;i++)
{
if(b[i].l>b[i-1].r)
{
int d=b[i].l-p;
if((d&1) && b[i].l+1<=b[i].r && b[i+1].l>b[i].r)p=b[i].l+1;
else p=b[i].l;
ans+=ceil(1.0*d/2);
}
else
{
int d=p-b[i].r;
if((d&1) && b[i].r-1>=b[i].l && b[i+1].r<b[i].l)p=b[i].r-1;
else p=b[i].r;
ans+=ceil(1.0*d/2);
}
}
}
int main()
{
// freopen("input.in","r",stdin);
cin>>T;
while(T--)
{
init();
solve();
cout<<ans<<endl;
}
return 0;
}