标签:多校
1 5 2 0 0 0 1 3 1 1 0 5 1 1 1 1 1
0 2 1 1 -1HintIf you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
题意:有n个点,排成一行,两个相邻点的距离为1,第 i 个点只能走相隔距离为 L[i]<=dis<=R[i],如果第 i 个点走到 第 j 个点花费为 cost[ i ],现在从1点开始,问能到的其他点 i 的最小花费为多少,不能到的点花费输出-1。
解题:因为每个点走到其他的点花费>=1,所以可以用SET 或 优先队列 按花费最小的点先取出,每个点只走一次。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
const int N = 310000;
#define ll __int64
struct NODE
{
int id;
ll cost;
friend bool operator < (NODE aa , NODE bb)
{
if(aa.cost==bb.cost)
return aa.id<bb.id;
return aa.cost<bb.cost;
}
};
set<NODE>node;
set<int>id;
ll C[N];
struct nnn
{
int l, r , cost;
}man[N];
int main()
{
int T,n;
NODE now , pre;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(C,-1,sizeof(C));
for(int i=1; i<=n; i++)
scanf("%d",&man[i].l);
for(int i=1; i<=n; i++)
scanf("%d",&man[i].r);
for(int i=1; i<=n; i++)
scanf("%d",&man[i].cost);
node.clear();
id.clear();
for(int i=2; i<=n; i++)
id.insert(i);
C[1]=0;
now.id=1;
now.cost=man[1].cost;
node.insert(now);
set<int>::iterator it,it1;
while(!node.empty())
{
now=*node.begin();
node.erase(node.begin());
int L,R;
L = now.id + man[now.id].l;
R = now.id + man[now.id].r;
it=id.lower_bound( L );
while(it!=id.end()&&*it<=R){
pre.id=*it;
pre.cost= now.cost + man[ pre.id ].cost;
node.insert( pre );
C[pre.id] = now.cost;
it1 = it++;
id.erase( it1 );
}
L = now.id - man[now.id].r;
R = now.id - man[now.id].l;
it = id.lower_bound( L );
while(it!=id.end()&&*it<=R){
pre.id=*it;
pre.cost = now.cost + man[ pre.id ].cost;
node.insert( pre );
C[pre.id]=now.cost;
it1=it++;
id.erase( it1 );
}
}
for(int i=1; i<=n; i++)
{
if(i!=1)printf(" ");
printf("%I64d",C[i]);
}
printf("\n");
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:多校
原文地址:http://blog.csdn.net/u010372095/article/details/47381753