题目集地址 Codeforces Round #773 (Div. 2)
A Hard Way
A
题目大意:一个三角形,如果从x轴任意一点能直接到达三角形上某个点且不穿过三角形的内部,那么这个点是安全的,问给出的三角形中不安全的部分的长度是多少。
思路:三角形与x轴平行的边,且这条边相对于三角形剩余的点距离x轴更远,那么不安全的部分就是这边的长度,否则就是0.
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
void solve()
{
int x1,x2,x3,y1,y2,y3;
cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
if(y1==y2&&y3<y1)
{
cout << abs(x1-x2) << endl;
}
else if(y2==y3&&y1 < y2)
{
cout << abs(x2-x3) << endl;
}
else if(y1==y3&&y2<y1)
{
cout << abs(x1-x3) <<endl;
}
else
{
cout << 0 << endl;
}
}
int main()
{
// freopen("in.txt","r",stdin);
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
B Power Walking
B
题目大意:有n张牌,每张牌有自己的类型,分发给k个人,每个人的分数等于他手中牌的类型数,对于每个k(
1
≤
k
≤
n
1\le k\le n
1≤k≤n)可能的最小总分是多少。
思路:自己手模一下就能找到规律,先统计一下牌的种类数m,
k
≤
m
k\le m
k≤m的时候,最小分数都是m,
k
>
m
k \gt m
k>m时,就是k
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
void solve()
{
int n;
cin >> n;
set<int> s;
for(int i = 1;i <= n;i++)
{
int t;
cin >> t;
s.insert(t);
}
int len = s.size();
for(int i = 1;i <= n;i++)
{
if(i<=len)
{
cout << len;
}
else{
cout << i;
}
if(i < n)
{
cout << " ";
}
else
{
cout << endl;
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
C Great Sequence
C
题目大意:给出一个数组,长度是2k,如果能将数组分割成k个数对,其中一个属是另一个数的2倍,这就是一个好的数组,问给出的数组最少需要添加多少个数能够满足是一个好的数组
思路:记录下每个数字出现的次数,存到一个map里面,遍历map,对于每一个数字,他的2倍对应的数字的数量如果小于他,最终的结果就要加上这个差值。遍历完即可。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
map<ll,ll> mll;
void solve()
{
int n,x;
cin >> n >> x;
for(int i = 1;i <= n;i++)
{
int t;
cin >> t;
mll[t]++;
}
map<ll,ll>::iterator it = mll.begin();
int ans=0;
for(;it!=mll.end();it++)
{
while(it->second)
{
if(mll[x*(it->first)])
{
mll[x*(it->first)]--;
}
else
{
ans++;
}
it->second--;
}
}
cout << ans << endl;
}
int main()
{
// freopen("in.txt","r",stdin);
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
D Repetitions Decoding
D
题目大意:给一个数组,可以执行以下操作,在任意位置添加两次相同的数字c,使数组满足以下条件,将数组分成若干组,每组的长度为偶数,保证每一组满足
x
i
=
=
x
i
+
k
x_i==x_{i+k}
xi==xi+k,输出执行的操作和最后的分组每组的长度。
思路:从第一个位置开始找,对于
a
i
a_i
ai找到与之相同的第一个数
a
j
a_j
aj,然后试图将这两个数分到一组中,依次对照
a
i
+
k
和
a
j
+
k
a_{i+k}和a_{j+k}
ai+k和aj+k的值是否相同,如果不同就在j+k的位置添加
a
i
+
k
a_{i+k}
ai+k两次,继续遍历直到i+k==j,此时找到一个分组,在遍历的过程中记录下自己的操作,记录下这个分组,之后i从(i+(j-i)*2)的位置继续遍历直到遍历完整个数组。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define pii pair<int,int>
using namespace std;
vector<int> vi;
void ins(int p,int c)
{
vi.insert(vi.begin()+p,c);
vi.insert(vi.begin()+p,c);
}
void solve()
{
vi.clear();
map<int,int> mii;
vector<pii> q;
vector<int> d;
int n;
scanf("%d",&n);
for(int i = 1;i<=n;i++)
{
int t;
scanf("%d",&t);
vi.push_back(t);
mii[t]++;
}
bool flag=true;
map<int,int>::iterator it=mii.begin();
for(;it!=mii.end();it++)
{
if((it->second)&1)
{
printf("-1\n");
flag=false;
break;
}
}
if(flag)
{
int i = 0,p=0;
while(i < n)
{
for(int j = i+1;j<n;j++)
{
if(vi[j]==vi[i])
{
p=j;
for(int k = 1;k < j-i;k++)
{
if(j+k>=n||vi[i+k]!=vi[j+k])
{
ins(j+k,vi[i+k]);
n+=2;
q.push_back(make_pair(j+k,vi[i+k]));
}
}
d.push_back((p-i)*2);
break;
}
}
i+=(p-i)*2;
}
cout << q.size() << endl;
for(i = 0;i < q.size();i++)
{
cout << q[i].first << " " << q[i].second << endl;
}
cout << d.size() << endl;
for(i = 0;i < d.size();i++)
{
cout << d[i];
if(i<d.size()-1)
{
cout << " ";
}
else
{
cout << endl;
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}