Ozon Tech Challenge 2020
A - Kuroni and the Gifts
题意
给你两个数组,要你改变顺序使得两个数组对应位置的和没有重复的值
复盘
一开始一个dfs写了老半天然后TLE20了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int N=114;
int n;
int a[N],b[N],ans[N];
int mp[3000],used[3000];
bool flag=false;
void dfs(int p)
{
if(p==n+1)
{
flag=true;
for(int i=1;i<=n;i++)
{
printf("%d ",a[i]);
}
printf("\n");
for(int i=1;i<=n;i++)
{
printf("%d ",ans[i]);
}
printf("\n");
return ;
}
if(flag==true)
{
return ;
}
for(int i=1;i<=n;i++)
{
if(flag==true)
{
return ;
}
int sum=a[p]+b[i];
if(used[i]==0 and mp[sum]==0)
{
used[i]=1;
mp[sum]=1;
ans[p]=b[i];
dfs(p+1);
used[i]=0;
mp[sum]=0;
}
}
}
void solve()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
}
flag=false;
memset(mp,0,sizeof(mp));
memset(used,0,sizeof(used));
dfs(1);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
然后发现其实只要分别sort一下就满足题意了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n;
scanf("%d",&n);
vector<int> a(n);
for (int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
vector<int> b(n);
for (int i=0;i<n;i++)
{
scanf("%d",&b[i]);
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
for (int i=0;i<n;i++)
{
printf("%d ",a[i]);
}
printf("\n");
for (int i=0;i<n;i++)
{
printf("%d ",b[i]);
}
printf("\n");
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
B - Kuroni and Simple Strings
题意
前一半都是‘(’,后一半都是‘)’的序列称为simple序列,现在给一个序列,每次可以删去一个simple子序列,问最少删多少次可以使得无法再继续删下去
思路
其实最多删1次就可以了,能删的我肯定可以一次性删完,那么具体怎么删呢,就是前后数一下,同时删去尽量多的就可以了
代码
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
string s;
cin>>s;
int n=s.size();
int l=0,r=n-1;
vector<int> lpos,rpos;
while(l<r)
{
while(l<n and s[l]==')')
l++;
while(r>=0 and s[r]=='(')
r--;
if(l>=r or l>=n or r<0)
break;
lpos.push_back(l+1);
rpos.push_back(r+1);
l++;
r--;
}
if(lpos.empty())
{
cout<<0<<endl;
return;
}
cout<<1<<endl;
cout<<lpos.size()*2<<endl;
for(int i=0;i<lpos.size();i++)
cout<<lpos[i]<<" ";
for(int i=lpos.size()-1;i>=0;i--)
cout<<rpos[i]<<" ";
cout<<endl;
}
int main()
{
int T=1;
//scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
Python
def solve():
s = input()
n = len(s)
l = 0
r = n - 1
lpos = []
rpos = []
while l < r:
while l < n and s[l] == ')':
l += 1
while r >= 0 and s[r] == '(':
r -= 1
if l >= r or l >= n or r < 0:
break
lpos.append(l + 1)
rpos.append(r + 1)
l += 1
r -= 1
if not lpos:
print(0)
return
print(1)
print(len(lpos) * 2)
for i in range(len(lpos)):
print(lpos[i], end=" ")
for i in range(len(lpos) - 1, -1, -1):
print(rpos[i], end=" ")
print()
T = 1
# T = int(input())
for _ in range(T):
solve()
C - Kuroni and Impossible Calculation
题意
给一个数组,计算所有二元数对的差值的绝对值的积
思路
一定要注意到m的范围只到1000,如果n大于m,根据抽屉法则,一定会出现模m后相等的两个数,就会导致最后的结果为0,那么如果小于m的话直接遍历就可以了
代码
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
vector<ll> a(n);
map<ll,ll> mp;
int flag=0;
for (ll i=0;i<n;i++)
{
scanf("%lld",&a[i]);
mp[a[i]%m]++;
if(mp[a[i]%m]>1)
flag=1;
}
if(flag==1)
{
printf("0\n");
return 0;
}
else
{
ll ans=1;
for (ll i=0;i<n;i++)
{
for (ll j=i+1;j<n;j++)
{
ans=ans*(abs(a[i]-a[j]))%m;
}
}
ans%=m;
printf("%lld\n",ans);
}
return 0;
}
Kotlin
import java.util.*
import kotlin.math.abs
fun main() {
val scanner = Scanner(System.`in`)
val n = scanner.nextLong()
val m = scanner.nextLong()
val a = LongArray(n.toInt())
val mp = mutableMapOf<Long, Long>()
var flag = 0
for (i in 0 until n) {
a[i.toInt()] = scanner.nextLong()
mp[a[i.toInt()] % m] = mp.getOrDefault(a[i.toInt()] % m, 0) + 1
if (mp[a[i.toInt()] % m]!! > 1)
flag = 1
}
if (flag == 1) {
println("0")
return
} else {
var ans = 1L
for (i in 0 until n) {
for (j in i + 1 until n) {
ans = ans * abs(a[i.toInt()] - a[j.toInt()]) % m
}
}
ans %= m
println("$ans")
}
}
D - Kuroni and the Celebration
题意
给你一棵树,但只知道边不知道谁爹谁儿子,你可以问 ⌊ n 2 ⌋ \lfloor \frac{n}{2} \rfloor ⌊2n⌋次任意两个节点的lca,找到这棵树的根节点
思路
找叶子节点,如果返回了他俩其中之一那就是返回的这个值,要不然就把这两个点都抹去,再更新叶子结点
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int N=1010;
int n;
vector<int> G[N];
int vn[N];
bool vis[N];
int ask(int u,int v)
{
printf("? %d %d\n",u,v);
fflush(stdout);
int x;
scanf("%d",&x);
return x;
}
int main()
{
scanf("%d",&n);
memset(vis,0,sizeof(vis));
memset(vn,0,sizeof(vn));
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
vn[x]++;
vn[y]++;
}
set<int> waiting;
for(int i=1;i<=n;i++)
{
if(vn[i]==1)
waiting.insert(i);
}
for(int i=1;i<=n/2;i++)
{
int u=*waiting.begin();
waiting.erase(u);
int v=*waiting.begin();
waiting.erase(v);
int w=ask(u,v);
if(w==u or w==v)
{
printf("! %d\n",w);
fflush(stdout);
return 0;
}
for(auto x:G[u])
{
if(vis[x])
continue;
if(--vn[x]==1)
waiting.insert(x);
}
for(auto x:G[v])
{
if(vis[x])
continue;
if(--vn[x]==1)
waiting.insert(x);
}
vis[u]=vis[v]=true;
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
printf("! %d\n",i);
fflush(stdout);
return 0;
}
}
return 0;
}
E - Kuroni and the Score Distribution
题意(洛谷的翻译)
构造一个序列
a
a
a 满足如下:
1、长度为
n
n
n 。
2、
∀
i
,
1
≤
a
i
≤
1
0
9
\forall i, 1\leq a_i\leq 10^9
∀i,1≤ai≤109 。
3、
∀
i
>
1
,
a
i
>
a
i
−
1
\forall i>1,a_i>a_{i-1}
∀i>1,ai>ai−1。
4、满足
i
<
j
<
k
i<j<k
i<j<k 且
a
i
+
a
j
=
a
k
a_i+a_j=a_k
ai+aj=ak 的三元组
(
i
,
j
,
k
)
(i,j,k)
(i,j,k) 数量恰好为
m
m
m。
n
≤
5000
,
m
≤
1
0
9
n\leq 5000,m\leq 10^9
n≤5000,m≤109 。
思路
先顺序填1,2,3…,然后按照规律,每填一个数都会贡献 ⌊ n − 1 2 ⌋ \lfloor \frac{n-1}{2} \rfloor ⌊2n−1⌋个三元组,等到超过了,再减去两倍多出的以控制,剩余的空位控制成毫无贡献的大数就行
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n, m;
scanf("%d%d", &n, &m);
vector<int> a(n);
int t = 0;
for (int i = 0; i < n; i++)
{
a[i] = i + 1;
t += i >> 1;
if (t >= m)
{
a[i] += (t - m) << 1;
for (int j = n - 1, k = 1e9; j > i; j--, k -= i + 2)
a[j] = k;
for (int j = 0; j < n; j++)
printf("%d ", a[j]);
return ;
}
}
printf("-1\n");
}
int main()
{
int T=1;
//scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}