传送门
简单模拟过后,我们发现如果一个数比两边都小的话
这个数最后一定会变成零
比如1 2 3 2 5 1 6 7
首先可以确定1 2 1会变成零,也就是
0 2 3 0 5 0 6 7
那么可以发现和 0 0 0相邻的可以变成 1 1 1…
但是其中 3 3 3也和 0 0 0相邻,但是因为左边的 2 2 2比自己小,所以不能小于左边的数
左边的 2 2 2可以变成 1 1 1,那么自己只能变成 2 2 2
我们发现,在相邻的数字=中,大的数依赖于小的数
这其实就是一张有向无环图,由小的数字像相邻大的数字连边去拓扑排序
不断松弛即可
拓扑代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6+10;
int in[maxn],t,n,a[maxn],f[maxn],casenum;
vector<int>vec[maxn];
void add(int u,int v){ vec[u].push_back( v ); in[v]++; }
void tuopu()
{
queue<int>q;
for(int i=1;i<=n;i++)
if( a[i]<a[i-1]&&a[i]<a[i+1] ) { f[i]=0; q.push( i ); }
while( !q.empty() )
{
int u = q.front(); q.pop();
for(int i=0;i<vec[u].size();i++)
{
int v = vec[u][i];
f[v] = max( f[v],f[u]+1 );
if( --in[v]==0 ) q.push( v );
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> t;
while( t-- )
{
int sum = 0;
cin >> n;
for(int i=1;i<=n;i++){ cin >> a[i]; sum += a[i]; }
a[0] = a[n+1] = 1e9+1;
for(int i=1;i<=n;i++)
{
if( a[i]<a[i-1]&&i-1>=1 ) add(i,i-1);
if( a[i]<a[i+1]&&i+1<=n ) add(i,i+1);
}
tuopu();
for(int i=1;i<=n;i++)
{
sum-=f[i],f[i]=0;
vec[i].clear();
}
cout << "Case " << ++casenum << ": ";
if( sum%2==1 ) cout << "Alice\n";
else cout << "Bob\n";
}
}
b f s bfs bfs代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6+10;
int in[maxn],t,n,a[maxn],f[maxn],casenum;
void bfs()
{
queue<int>q;
for(int i=1;i<=n;i++)
if( a[i]<a[i-1]&&a[i]<a[i+1] ) { f[i]=0; q.push( i ); }
while( !q.empty() )
{
int u = q.front(); q.pop();
if( u-1>=1&&a[u-1]>a[u] )
{
f[u-1] = max( f[u-1],f[u]+1 );
q.push( u-1 );
}
if( u+1<=n&&a[u+1]>a[u] )
{
f[u+1] = max( f[u+1],f[u]+1 );
q.push( u+1 );
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> t;
while( t-- )
{
int sum = 0;
cin >> n;
for(int i=1;i<=n;i++){ cin >> a[i]; sum += a[i]; }
a[0] = a[n+1] = 1e9+1;
bfs();
for(int i=1;i<=n;i++)
sum-=f[i],f[i]=0;
cout << "Case " << ++casenum << ": ";
if( sum%2==1 ) cout << "Alice\n";
else cout << "Bob\n";
}
}