BZOJ4053 : [Cerc2013]Subway

通过BFS可以求出到每个站点的最小花费。

每次从队首取出一个点,枚举所有它能花费1块钱就到达的线路,通过两遍递推求出最大时间。

注意到每个点和每条线路只有第一次使用时有用,所以总时间复杂度为$O(n+m)$。

#include<cstdio>
#include<cstring>
#include<algorithm>
typedef unsigned long long ll;
const int N=300010,M=100010,E=1000010,inf=1000000000;
int Case,n,m,i,j,k,l,D,S,T,a[E],cnt,st[M],en[M],g[N],v[E],nxt[E],ed;
int q[N],h,t,d[N],f[N];bool vis[N],use[M];
char s[18000000],sS[55],sT[55];ll b[N];
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline bool check(char x){
  if(x>=‘a‘&&x<=‘z‘)return 1;
  if(x>=‘A‘&&x<=‘Z‘)return 1;
  if(x>=‘0‘&&x<=‘9‘)return 1;
  return x==‘-‘||x==‘\‘‘||x==‘&‘;
}
inline ll gethash(int l,int r){
  ll t=0;
  for(int i=l;i<r;i++)t=t*233+s[i];
  return t;
}
inline ll getname(char*s){
  scanf("%s",s);
  int l=strlen(s);ll t=0;
  for(int i=0;i<l;i++)t=t*233+s[i];
  return t;
}
inline int ask(ll x){
  int l=1,r=n,mid;
  while(1){
    if(b[mid=(l+r)>>1]==x)return mid;
    if(b[mid]<x)l=mid+1;else r=mid-1;
  }
}
inline void up(int&x,int y){if(x<y)x=y;}
inline void solve(int x){
  if(use[x])return;
  use[x]=1;
  int i,tmp;
  for(i=st[x];i<=en[x];i++)if(!vis[a[i]])vis[q[++t]=a[i]]=1,d[a[i]]=D+1;
  for(tmp=-inf,i=st[x];i<=en[x];i++)if(d[a[i]]==D)up(tmp,f[a[i]]-i);else up(f[a[i]],tmp+i);
  for(tmp=-inf,i=en[x];i>=st[x];i--)if(d[a[i]]==D)up(tmp,f[a[i]]+i);else up(f[a[i]],tmp-i);
}
int main(){
  scanf("%d",&Case);
  while(Case--){
    scanf("%s",s);
    gets(s);
    l=strlen(s);
    for(n=i=0;i<l;)if(!check(s[i]))i++;else{
      for(j=i;j<l&&check(s[j]);j++);
      b[++n]=gethash(i,j);
      i=j;
    }
    std::sort(b+1,b+n+1);
    for(ed=0,i=1;i<=n;i++)g[i]=0;
    scanf("%s",s);
    gets(s);
    l=strlen(s);
    for(m=i=0;i<l;)if(!check(s[i]))i++;else{
      for(j=i;j<l&&check(s[j]);j++);
      m++;
      i=j;
    }
    for(cnt=0,k=1;k<=m;k++){
      scanf("%s",s);
      scanf("%s",s);
      gets(s);
      l=strlen(s);
      st[k]=cnt+1;
      for(i=0;i<l;)if(!check(s[i]))i++;else{
        for(j=i;j<l&&check(s[j]);j++);
        a[++cnt]=ask(gethash(i,j));
        i=j;
      }
      en[k]=cnt;
      for(j=st[k];j<=en[k];j++)add(a[j],k);
      use[k]=0;
    }
    scanf("%s",s);
    scanf("%s",s);
    scanf("%s",s);
    S=ask(getname(sS));
    scanf("%s",s);
    scanf("%s",s);
    scanf("%s",s);
    T=ask(getname(sT));
    for(i=1;i<=n;i++)d[i]=inf,f[i]=vis[i]=0;
    d[S]=f[S]=0;
    vis[S]=1;
    q[h=t=1]=S;
    while(h<=t){
      D=d[q[h]];
      while(h<=t&&d[q[h]]==D)for(i=g[q[h++]];i;i=nxt[i])solve(v[i]);
    }
    printf("optimal travel from %s to %s: %d line",sS,sT,d[T]);
    if(d[T]>1)putchar(‘s‘);
    printf(", %d minute",f[T]);
    if(f[T]>1)putchar(‘s‘);
    puts("");
  }
  return 0;
}

  

时间: 2024-10-07 05:50:02

BZOJ4053 : [Cerc2013]Subway的相关文章

Codeforces 371E Subway Innovation (前缀和预处理应用)

题目链接 Subway Innovation 首先不难想到所求的k个点一定是连续的,那么假设先选最前面的k个点,然后在O(1)内判断第2个点到第k+1个点这k个点哪个更优. 判断的时候用detla[i]来记录信息.令delta[k+1]+delta[k+2]+......+delta[k+x] = sum[x],则sum[x]最大时,x即为排完序后的要选的k个点的最大的编号. #include <bits/stdc++.h> using namespace std; #define rep(i

第一次作业——subway

作业源程序代码:https://github.com/R-81/subway 作业程序使用说明:通过输入命令参数求解路线(仅支持-b,-c),根据参数得出路线后,程序不会结束,此时可输入地铁路线名(例如地铁一号线)输出此路线上所有车站名. 1)各模块开发需要消耗的时间   Personal Software Process Stages Time Planning 计划 · Estimate · 估计这个任务需要多少时间 15h Development 开发 · Analysis · 需求分析 

ural 1272. Non-Yekaterinburg Subway

1272. Non-Yekaterinburg Subway Time limit: 1.0 secondMemory limit: 64 MB A little town started to construct a subway. The peculiarity of the town is that it is located on small islands, some of them are connected with tunnels or bridges. The mayor is

【BZOJ】【4052】【CERC2013】Magical GCD

DP/GCD 然而蒟蒻并不会做…… Orz @lct1999神犇 首先我们肯定是要枚举下端点的……嗯就枚举右端点吧…… 那么对于不同的GCD,对应的左端点最多有log(a[i])个:因为每次gcd缩小,至少变成gcd/2(2是最小的质因数),所以是log个左端点…… 所以我们就有了log段!每段的gcd是相同的.当我们加入一个新的右端点时,除了该节点本身外,不会出现新的左端点,原有的左端点可能会不变,或是两(多)段合并成一段,用滚动数组记一下,暴力搞就可以了……$O(n*log^2n)$ Orz

(简单) POJ 2502 Subway,Dijkstra。

Description You have just moved from a quiet Waterloo neighbourhood to a big, noisy city. Instead of getting to ride your bike to school every day, you now get to walk and take the subway. Because you don't want to be late for class, you want to know

URAL(timus) 1272 Non-Yekaterinburg Subway(最小生成树)

Non-Yekaterinburg Subway Time limit: 1.0 secondMemory limit: 64 MB A little town started to construct a subway. The peculiarity of the town is that it is located on small islands, some of them are connected with tunnels or bridges. The mayor is sure

【POJ】【1635】Subway Tree Systems

树的最小表示法 给定两个有根树的dfs序,问这两棵树是否同构 题解:http://blog.sina.com.cn/s/blog_a4c6b95201017tlz.html 题目要求判断两棵树是否是同构的,思路是用树的最小表示法去做.这里用的最小表示法就是将树的所有子树分别用1个字符串表示,要按字典序排序将他们依依连接起来.连接后如果两个字符串是一模一样的,那么他们必然是同构的.这样原问题就变成了子问题,子树又是一颗新的树. 1 Source Code 2 Problem: 1635 User:

[有向树的最小表示] poj 1635 Subway tree systems

题目链接: http://poj.org/problem?id=1635 Subway tree systems Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6541   Accepted: 2747 Description Some major cities have subway systems in the form of a tree, i.e. between any pair of stations, th

【BZOJ4052】[Cerc2013]Magical GCD 乱搞

[BZOJ4052][Cerc2013]Magical GCD Description 给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12. 求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大. Sample Input 1 5 30 60 20 20 20 Sample Output 80 题解:先思考暴力的做法.我们从一个数开始往左扫,将所有使得gcd改变的位置都记录下来.由于gcd的每次改变都至少/2,所以这样的位置不超过log个. 那么我们