2017-多校-8-1004 模拟
被模拟题搞翻了,搞了一下午,真TM傻逼
思路:
- 处理相对运动,最后一个肯定是最后的赢家,求出其他的相对速度和相对位置,将最后一个参赛者放到位置0
- 处理可以从两个方向不被反方向行走参赛者干掉,能够到达原点的参赛者并标记出来
- 然后处理同一个方向的能够最终到达原点的参赛者,比较这些参赛者,找出到达原点的最长时间。
调了无数遍的代码,终于A了
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <math.h>
#include <bitset>
#define CLS(x) memset(x, 0, sizeof(x))
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 2e5 + 5;
const int mod = 1e9 + 7;
int L,n;
struct Node
{
int x;
int pow;
int v;
};
bool cmp(Node a, Node b)
{
return a.x < b.x;
}
Node node[N];
int t;
int rvis[N], lvis[N];
LL gcd(LL a, LL b)
{
return b == 0 ? a : gcd(b, a%b);
}
int main()
{
//freopen("1004.in","r",stdin);
//freopen("1004.out","w",stdout);
while(1 == scanf("%d", &t))
{
while(t--)
{
CLS(node);
scanf("%d%d", &n,&L);
for(int i = 1; i <= n; i++)
{
scanf("%d", &node[i].x);
node[i].pow = i;
}
for(int i = 1; i <= n; i++)
scanf("%d", &node[i].v);
int sx,sp,sv;
sx = node[n].x;
sp = node[n].pow;
sv = node[n].v;
for(int i = 1; i <= n; i++)
{
node[i].v -= sv;
node[i].x -= sx;
if(node[i].x < 0) node[i].x += L;
}
sort(node + 1, node + 1 + n, cmp);
CLS(lvis); CLS(rvis);
int mxp = 0;
for(int i = 2; i <= n; i++)
{
if(node[i].v > 0)
mxp = max(mxp, node[i].pow);
else
{
if(node[i].pow > mxp)
{
lvis[i] = 1;
mxp = 0;
}
}
}
mxp = 0;
for(int i = n; i >= 2; i--)
{
if(node[i].v < 0)
mxp = max(mxp, node[i].pow);
else
{
if(node[i].pow > mxp)
{
rvis[i] = 1;
mxp = 0;
}
}
}
LL ansS = 0,ansV = 1, ansP = 0;
stack<Node> s;
LL ss = 0, vv = 1;
for(int i = 2; i <= n; i++)
{
if(lvis[i])
{
Node p = node[i];
p.v = -p.v;
int f = 0;
while(!s.empty() && (LL)s.top().x*p.v >= (LL)s.top().v*p.x)
{
if(s.top().pow < p.pow)
s.pop();
else
{
f = 1;
break;
}
}
if(!f)
s.push(p);
}
}
while(!s.empty())
{
if((LL)s.top().x*(LL)vv > (LL)s.top().v*(LL)ss)
{
ss = s.top().x;
vv = s.top().v;
}
s.pop();
}
ansS = ss;
ansV = vv;
ss = 0, vv = 1;
for(int i = n; i >= 2; i--)
{
if(rvis[i])
{
Node p = node[i];
p.x = L - p.x;
int f = 0;
while(!s.empty() && (LL)s.top().x*(LL)p.v >= (LL)s.top().v*(LL)p.x)
{
if(p.pow > s.top().pow)
s.pop();
else
{
f = 1;
break;
}
}
if(!f)
s.push(p);
}
}
while(!s.empty())
{
if((LL)s.top().x*(LL)vv > (LL)s.top().v*(LL)ss)
{
ss = s.top().x;
vv = s.top().v;
}
s.pop();
}
if(1LL*ss*ansV > 1LL*ansS*vv)
ansS = ss, ansV = vv;
LL g = gcd(ansS, ansV);
printf("%lld/%lld
", ansS/g, ansV/g);
}
}
return 0;
}
错误原因:
- 当时觉的正着搞有点麻烦,
没想到用栈。 - 所以就反着找,比如考虑向左方向行进的参赛者,最后一个右边参赛者p往左边行进,如果左边的行进者p1武器比他垃圾,如果p1的速度小,会被p搞死,p1的速度大,那么p用的时间就比p1多了。如果p1的武器比p厉害,并且p1行进的比较慢,所以最后p会追上p1,然后被p1杀掉。所以更新方式就是只有遇到武器威力大,所用时间长的参赛者才会更新。
- 但是,问题就是,p行进路上前面有两个参赛者,前面有一个跑的快的而且威力超级大,一个威力比p大,跑的慢,那个跑的快的会先把跑得慢的干掉。所以,就不能向上面的决策来处理了。
错误代码:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <math.h>
#include <bitset>
#define CLS(x) memset(x, 0, sizeof(x))
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 2e5 + 5;
const int mod = 1e9 + 7;
int L,n;
struct Node
{
int x;
int pow;
int v;
};
bool cmp(Node a, Node b)
{
return a.x < b.x;
}
Node node[N];
int t;
int rvis[N], lvis[N];
int S[N], V[N];
LL gcd(LL a, LL b)
{
return b == 0 ? a : gcd(b, a%b);
}
int main()
{
freopen("1004.in","r",stdin);
freopen("10040.out","w",stdout);
while(1 == scanf("%d", &t))
{
while(t--)
{
CLS(node);
CLS(S);
CLS(V);
scanf("%d%d", &n,&L);
for(int i = 1; i <= n; i++)
{
scanf("%d", &node[i].x);
node[i].pow = i;
}
for(int i = 1; i <= n; i++)
scanf("%d", &node[i].v);
int sx,sp,sv;
sx = node[n].x;
sp = node[n].pow;
sv = node[n].v;
for(int i = 1; i <= n; i++)
{
node[i].v -= sv;
node[i].x -= sx;
if(node[i].x < 0) node[i].x += L;
}
sort(node + 1, node + 1 + n, cmp);
for(int i = 2; i <= n; i++)
{
if(node[i].v > 0)
{
S[i] = L-node[i].x;
V[i] = node[i].v;
}
else
{
S[i] = node[i].x;
V[i] = -node[i].v;
}
}
CLS(lvis);
CLS(rvis);
int mxp = 0;
int cnt = 0;
for(int i = 2; i <= n; i++)
{
if(node[i].v > 0)
mxp = max(mxp, node[i].pow);
else
{
if(node[i].pow > mxp)
{
lvis[i] = 1;
cnt++;
mxp = 0;
}
}
}
cout<<cnt<<endl;
mxp = 0;
for(int i = n; i >= 2; i--)
{
if(node[i].v < 0)
mxp = max(mxp, node[i].pow);
else
{
if(node[i].pow > mxp)
{
rvis[i] = 1;
mxp = 0;
}
}
}
int pos = -1;
for(int i = n; i >= 2; i--)
{
if(lvis[i])
{
pos = i;
break;
}
}
printf("pos=%d ", pos);
LL ansS = 0,ansV = 1, ansP = 0;
int s2,v2;
for(int i = n; i >= 2; i--)
{
if(lvis[i])
{
if(node[i].pow > ansP && S[i]*ansV > V[i]*ansS)
{
ansS = S[i];
ansV = V[i];
ansP = node[i].pow;
}
}
}
s2 = ansS;
v2 = ansV;
ansP = 0;
ansS = 0;
ansV = 1;
for(int i = 2; i <= n; i++)
{
if(rvis[i])
{
if(node[i].pow > ansP && S[i]*ansV > V[i]*ansS)
{
ansS = S[i];
ansV = V[i];
ansP = node[i].pow;
}
}
}
if(1LL*(long long)s2*ansV > 1LL*(long long)ansS*v2)
ansS = s2, ansV = v2;
LL g = gcd(ansS, ansV);
printf("%lld/%lld
", ansS, ansV);
}
}
return 0;
}