ZOJ Problem Set - 3888 Twelves Monkeys
Chieh
posted @ 2015年7月29日 11:12
in ZOJ
, 286 阅读
飞机票:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3888
题意:给你n年,其中有m中关系,Xi Yi,代表从第Xi年可以回到Yi年,其中 Xi>=Yi,然后给你Q个查询,每个查询一个年份q,问你从第q年,至少有两种方案可以回到q年之前的年份有多少年。然后后面就是给你解释,第q年可以等到q年之后然后在回到q年之前。或则直接走,但是m种关系在一条路径中只能用一次。
分析:假设当前查询的是q年,那么我们要知道我们能回到q年之前至少有两条路径有多少年,我们可以从q~n之间的最小Yi和次小Yi。为什么,因为q可以等到q~n之间的一年然后回到最小Yi,或则q可以等到q~n之间的一年然后回到次小Yi,这样就有两条路径可以回到Yi到q之间的年份,且因为次小Yi是第二小的,所以剩下的都大于次小Yi,所以次小Yi是最优的。那么就可以从后往前推,每次更新次小Yi。然后查询的话,如果次小Yi大于等于q,那么就是0,因为回不去,如果小于q,那么就可以会q-次小Yi年,这样的话就Ok了,最后啪啪啪就可以AC了
/* Author:Chieh Because Of Coding */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #include <stack> #define LL long long #define INF 1e9 #define EPS 1e-9 using namespace std; const int maxn=5*12345; struct he { int x,y; } Sky[maxn]; int n,m,q; bool cmp(he a,he b) { return a.x>b.x; } void init() { for(int i=1; i<=m; i++)scanf("%d%d",&Sky[i].x,&Sky[i].y); sort(Sky+1,Sky+1+m,cmp); } int ai[maxn]; void play() { memset(ai,0,sizeof(ai)); int l1=-1,l2=-1; for(int i=1; i<=m; i++) { int now=Sky[i].x; int next=Sky[i].y; if(l1==-1)l1=next; else if(l2==-1) { if(l1>next) { l2=l1; l1=next; } else { l2=next; } } else { if(next<l1) { l2=l1; l1=next; } else if(next<l2) { l2=next; } } ai[now]=l2; } for(int i=n; i>=1; i--) { if(ai[i]==-1)continue; if(ai[i]==0) { ai[i]=ai[i+1]; } } int t; while(q--) { scanf("%d",&t); if(ai[t]==-1||ai[t]==0)printf("0\n"); else { if(ai[t]>=t)printf("0\n"); else printf("%d\n",t-ai[t]); } } } int main() { while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init(); play(); } // cout << "Hello world!" << endl; return 0; }