JL老贼的一道联赛T3难度的好题

小Z的推冰块
ice.cpp/in/out
时间限制:1s
题目描述
空间限制:256MB

思路{

  首先发现减速带的消除操作是无意义的.因为正权环一定不会最优,

  $n,m$有点大,但是$k$比较小,发现一个点停留的位置只有$k$的级别,然后就相当于是跑最短路了.

  关键就是把图建出来.

  首先把所有特殊点抠出来,再搞两个$set$分别找到上下和左右的第一个特殊点,连边最短路.

  自我感觉还算不错的一道$NOIP$题吧~~~~.

}

#include<bits/stdc++.h>
#define ll long long
#define RG register
#define il inline
#define N 6000005
#define Mo 6000005
#define int long long
using namespace std;
int d[N],n,m,hsh[N],k;
struct dat1{
    int x,y,flag;
    bool operator <(const dat1 & a)const{
	return x==a.x?y<a.y:x<a.x;
    }
};
struct dat2{
    int x,y,flag;
    bool operator <(const dat2 & a)const{
	return y==a.y?x<a.x:y<a.y;
    }
};
int pos(int x,int y){
    ll Hsh=1ll*(x-1)*m+y;
    int num=(Hsh%Mo);
    while(hsh[num]&&hsh[num]!=Hsh)num++;
    hsh[num]=Hsh;
    return num;
}
bool in[N];
set<dat1>s1;
set<dat1>::iterator it1;
set<dat2>s2;
set<dat2>::iterator it2;

queue<int>qx,qy;
void Modify(int u,int x,int y,int flag){
    int v=pos(x,y);
    if(d[v]>d[u]+1){
	d[v]=d[u]+1;
	if(!in[v])in[v]=1,qx.push(x),qy.push(y);
    }
}
void modify(int x,int y){
    int u=pos(x,y);
    it1=s1.upper_bound((dat1){x,y,233});
    dat1 temp=*it1;int xx=temp.x,yy=temp.y,F=temp.flag;
    if(temp.x!=x)xx=x,yy=m,F=-1;
    if(!F)yy--;Modify(u,xx,yy,F);

    it1=s1.lower_bound((dat1){x,y,233});
    it1--;
    temp=*it1;xx=temp.x,yy=temp.y,F=temp.flag;
    if(temp.x!=x)xx=x,yy=1,F=-1;
    if(!F)yy++;Modify(u,xx,yy,F);

    it2=s2.upper_bound((dat2){x,y,233});
    dat2 tmp=*it2;xx=tmp.x,yy=tmp.y,F=tmp.flag;
    if(yy!=y)xx=n,yy=y,F=-1;
    if(!F)xx--;Modify(u,xx,yy,F);

    it2=s2.lower_bound((dat2){x,y,233});
    it2--;
    tmp=*it2;xx=tmp.x,yy=tmp.y,F=tmp.flag;
    if(yy!=y)xx=1,yy=y,F=-1;
    if(!F)xx++;Modify(u,xx,yy,F);
}
void spfa(){
    memset(d,127,sizeof(d));
    qx.push(1),qy.push(1);
    d[pos(1,1)]=0; in[pos(1,1)]=0;
    while(!qx.empty()){
	int x=qx.front(),y=qy.front();qx.pop(),qy.pop();
	in[pos(x,y)]=0;
	modify(x,y);
    }
    cout<<d[pos(n,m)];
}
main(){
  freopen("ice.in","r",stdin);
  freopen("ice.out","w",stdout);
  scanf("%lld%lld",&n,&m);int flag;scanf("%lld",&k);
  for(int i=1;i<=k;++i){
      int x,y;scanf("%lld%lld%lld",&x,&y,&flag);
      s1.insert((dat1){x,y,flag});
      s2.insert((dat2){x,y,flag});
  }
  s1.insert((dat1){n,m,233});
  s2.insert((dat2){n,m,233});
  spfa();
  return 0;
}

 

posted @ 2017-11-07 18:57  QYP_2002  阅读(258)  评论(0编辑  收藏  举报