A. Milya and Two Arrays
解析:我们发现c数组是由a和b数组累加来的,我们可以对a数组进行 随意的排序,因为a,b数组都是好数组,我们会发现只有三种情况满足最终的情况
1.a和b数组去重后的个数都等于2
2.a数组去重后的个数大于2,b数组可以任意
3.a数组任意,b数组去重后的个数大于2
这三种情况是满足最终结果的,只需要用一个set存储,去判断其size大小即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a;
int b;
string s;
void solve()
{
cin>>n;
set<int> s1;
set<int> s2;
for(int i=1;i<=n;i++)
{
cin>>a;
s1.insert(a);
}
for(int j=1;j<=n;j++)
{
cin>>b;
s2.insert(b);
}
if((s1.size()==2&&s2.size()==2)||(s1.size()>2)||(s2.size()>2))
{
cout<<"YES\n";
}
else
{
cout<<"NO\n";
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
solve();
return 0;
}
B. Cost of the Array
思路:我们可以发现最大的组内个数为n-k+1个,因此我们可以对其分情况讨论
1.首先当k<n时,我们可以看从2到n-k+2的情况
如果都是1,那么结果最终为2,我们可以将前,我们可以将2~n-k+作为一组,那么第二个一定为1,所以最终答案为2
如果不都是1,那么我们可以将不是1的数作为b数组的第一项,那么答案就是1
2.当n=k的情况,我们直接暴力就行
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a[200005];
string s;
void solve()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
if(k!=n)
{
int flag=0;
for(int i=2;i<=2+n-k;i++)
{
if(a[i]!=1)
{
flag=1;
break;
}
}
if(flag==0)
{
cout<<2<<"\n";
}
else
{
cout<<1<<"\n";
}
}
else
{
for(int i=2;i<=n;i+=2)
{
if(a[i]!=i/2)
{
cout<<i/2<<"\n";
return;
}
}
cout<<n/2+1<<"\n";
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
solve();
return 0;
}
C. Customer Service
思路:一开始我想的是后缀和,但是发现自己想复杂了,我们还是用逆向思维,假设我们要让mex为2,那就说明有一行是这样的状态xxxxx1,如果要让mex为3,那就说明除了上述那一行,还要有一行的状态为xxxx11
因为每次都会删除一行为0,所以mex必然是大于0的,我t只需要用multise(无去重的set)统计每一行后缀1的个数即可,当我们后缀为1的数量大于等于mex的时候,就可以让mex的值++
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int a[305][305];
void solve()
{
cin>>n;
multiset<int> s;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
int cnt=0;
for(int j=n;j>=1;j--)
{
if(a[i][j]==1)
{
cnt++;
}
else
{
break;
}
}
s.insert(cnt);
}
int mex=0;
for(int u:s)
{
if(u>=mex)
{
mex++;
}
}
cout<<mex<<"\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
solve();
return 0;
}
D. Graph and Graph
思路: 对第三组数据手玩了一下,发现,只有当他们走到同一个点上,并且有一个边的顶点是相同的时候才会出现最小成本,否则就是无限大。因此我们可以用逆向思维来解决这个问题,我们可以先找到所有的可能出现的结果,然后逆向去bfs,我们让每个点只走一次,去寻找所有可能的出现的结果,如果遇到一图中的点为s1且二图中的点为s2的时候就立即更新结果,结束循环最终输出结果即可,我是用tuple去组成元组
不会的可以看博客详解tuple用法
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
int s1,s2;
int m1,m2;
int ans=-1;
int d,u,v;
struct node{
int d;
int u1;
int u2;
};
void solve()
{
ans=-1;
cin>>n>>s1>>s2;
cin>>m1;
vector<int> e1[n+1];
vector<pair<int,int>> edge1;
for(int i=1;i<=m1;i++)
{
cin>>u>>v;
e1[u].push_back(v);
e1[v].push_back(u);
pair<int,int> p=make_pair(u,v);
edge1.push_back(p);
}
cin>>m2;
vector<int> e2[n+1];
vector<pair<int,int>> edge2;
for(int i=1;i<=m2;i++)
{
cin>>u>>v;
e2[u].push_back(v);
e2[v].push_back(u);
pair<int,int> p=make_pair(u,v);
edge2.push_back(p);
}
priority_queue<tuple<int, int, int>,vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> que;
for(pair<int,int> p1:edge1)
{
for(pair<int,int> p2:edge2)
{
int u1=p1.first;
int v1=p1.second;
int u2=p2.first;
int v2=p2.second;
if(u1==u2&&v1==v2)
{
que.push((tuple<int,int,int>){0,u1,u1});
}
if(u1==v2&&v1==u2)
{
que.push((tuple<int,int,int>){0,u1,u1});
}
}
}
vector<vector<int>> vis(n + 1, vector<int>(n + 1, 0));
while(!que.empty())
{
tuple<int,int,int> tu=que.top();
que.pop();
d=get<0>(tu);
u=get<1>(tu);
v=get<2>(tu);
if(vis[u][v]==1)
continue;
if(u==s1&&v==s2)
{
ans=d;
break;
}
vis[u][v]=1;
d+=abs(u-v);
for(int u2:e1[u])
{
for(int v2:e2[v])
{
que.push(tuple<int,int,int>(d,u2,v2));
}
}
}
cout<<ans<<"\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
solve();
return 0;
}