Codeforces Round #805 (Div. 3) A C D E F题解
A.
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<string>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
typedef long long ll;
using namespace std;
typedef unsigned long long int ull;
#define maxn 200005
#define ms(x) memset(x,0,sizeof(x))
#define Inf 0x7fffffff
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
#define pi acos(-1.0)
#define pii pair<int,int>
#define eps 1e-5
#define pll pair<ll,ll>
#define lson 2*x
#define rson 2*x+1
long long qupower(int a, int b) {
long long ans = 1;
while (b) {
if (b & 1)ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
inline int read() {
int an = 0, x = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') {
x = -1;
}
c = getchar();
}
while (c >= '0'&&c <= '9') {
an = an * 10 + c - '0'; c = getchar();
}
return an * x;
}
int t;
int m;
int find_round(int x){
int ans = 1;
while(ans<=x){ans = ans*10;}
return ans/10;
}
int main(){
//ios::sync_with_stdio(false);
t = read();
while(t--){
scanf("%d",&m);
cout<<m - find_round(m)<<endl;
}
}
C.
problem C
给定一个序列,询问是否存在一个数对 (\(a,b\)) 在序列中。 暴力做法:枚举 \(a\),看 \(a\) 后面的序列中是否出现 \(b\), 复杂度 \(O(N^2)\) 不允许。实际上我们可以用 \(vector\) 来记录每个数出现的位置,显然这些位置是从小到大的。如果 \(a\) 的位置区间最小值大于 \(b\) 的位置区间最大值,显然不可能
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<string>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
typedef long long ll;
using namespace std;
typedef unsigned long long int ull;
#define maxn 200005
#define ms(x) memset(x,0,sizeof(x))
#define Inf 0x7fffffff
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
#define pi acos(-1.0)
#define pii pair<int,int>
#define eps 1e-5
#define pll pair<ll,ll>
#define lson 2*x
#define rson 2*x+1
long long qupower(int a, int b) {
long long ans = 1;
while (b) {
if (b & 1)ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
inline int read() {
int an = 0, x = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') {
x = -1;
}
c = getchar();
}
while (c >= '0'&&c <= '9') {
an = an * 10 + c - '0'; c = getchar();
}
return an * x;
}
int n;
int t;
int u[200005];
int main(){
//ios::sync_with_stdio(false);
cin>>t;
while(t--){
cout<<endl;
n = read();
int k = read();
ms(u);
map<int, pair<int,int> > loc;
for(int i=0;i<n;i++)u[i] = read();
for(int i=0;i<n;i++){
if(!loc.count(u[i])){
loc[u[i]] = make_pair(i,i);
}
else{
loc[u[i]].second = i;
}
}
while(k--){
int a =read(), b = read();
if(!loc.count(a) || !loc.count(b) || loc[a].first>loc[b].second){
printf("NO\n");
}
else{
printf("YES\n");
}
}
}
}
D.
problem D
给定一个字符串,以及一个限制 \(p\),删除最小数量的字符使得字符串的 \(sum\leq p\). 并且保留字符串中字符原有的顺序。
那么我们贪心地去删除显然是选大的去删
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<string>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
typedef long long ll;
using namespace std;
typedef unsigned long long int ull;
#define maxn 200005
#define ms(x) memset(x,0,sizeof(x))
#define Inf 0x7fffffff
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
#define pi acos(-1.0)
#define pii pair<int,int>
#define eps 1e-5
#define pll pair<ll,ll>
#define lson 2*x
#define rson 2*x+1
long long qupower(int a, int b) {
long long ans = 1;
while (b) {
if (b & 1)ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
inline int read() {
int an = 0, x = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') {
x = -1;
}
c = getchar();
}
while (c >= '0'&&c <= '9') {
an = an * 10 + c - '0'; c = getchar();
}
return an * x;
}
int t;
string s;
int p;
int map_to_int(char x){
return x-'a'+1;
}
vector<char> vec;
map<char,int> mp;
int cal_sum(string s){
int n = s.length();
int ans = 0;
for(int i=0;i<n;i++){
ans += (s[i]-'a'+1);
}
return ans;
}
int main(){
//ios::sync_with_stdio(false);
t = read();
while(t--){
cin>>s;
int comp = cal_sum(s);
cin>>p;
if(p>=comp) cout<<s<<endl;
else{
vec.clear(); mp.clear();
string ans="";
int n = s.length();
int Min = 30;
for(int i=0;i<n;i++)vec.push_back(s[i]), Min = min(Min,map_to_int(s[i]));
if(Min>p){
cout<<""<<endl;
}
else{
sort(vec.begin(),vec.end()); reverse(vec.begin(),vec.end());
for(int i=0;i<n;i++){
// cout<<vec[i]<<" ";
if(comp-map_to_int(vec[i])<=p){
mp[vec[i]]++; break;
}
mp[vec[i]]++;comp -= map_to_int(vec[i]);
}
for(int i=0;i<n;i++){
if(mp[s[i]]==0){
ans = ans+s[i];
}
else mp[s[i]]--;
}
cout<<ans<<endl;
}
}
}
}
E.
problem D
给定 \(n\) 个多米诺骨牌,且多米诺上的数字范围 \(1\sim n\),每个多米诺上面有 \(2\) 个数。问能否将这些分成两个集合,且每个集合里面的数字不一样。
思路:分成两个集合, 每个集合大小为 \(n\) ----> 每个集合的数字都不一样: 必须 \(1,2,...,n\) 都出现一次。不妨将多米诺上面的数字看作边:\((x,y)\) 表示 \(x,y\) 之间有一条边。所以会形成一个个的小环。什么情况下才能满足条件呢?我们从一个点出发,遍历结束得到的环长度为偶数才可以,否则奇数环必然分到一个相同的元素。
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<string>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
typedef long long ll;
using namespace std;
typedef unsigned long long int ull;
#define maxn 200005
#define ms(x) memset(x,0,sizeof(x))
#define Inf 0x7fffffff
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
#define pi acos(-1.0)
#define pii pair<int,int>
#define eps 1e-5
#define pll pair<ll,ll>
#define lson 2*x
#define rson 2*x+1
long long qupower(int a, int b) {
long long ans = 1;
while (b) {
if (b & 1)ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
inline int read() {
int an = 0, x = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') {
x = -1;
}
c = getchar();
}
while (c >= '0'&&c <= '9') {
an = an * 10 + c - '0'; c = getchar();
}
return an * x;
}
int t;
map<int, vector<int> > edge;
int vis[200005];
int dfs(int x){
vis[x] = 1;
for(auto v: edge[x]){
if(!vis[v])return dfs(v)+1;
}
return 1;
}
void solve(){
int n = read();
edge.clear(); ms(vis);
bool fg = false;
for(int i=0;i<n;i++){
int a = read(), b = read();
edge[a].push_back(b); edge[b].push_back(a);
if(a==b || edge[a].size()>2 || edge[b].size()>2)fg = true;
}
if(fg){
printf("NO\n");
return;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
if(dfs(i)%2){
printf("NO\n");
return;
}
}
}
printf("YES\n");
}
int main(){
//ios::sync_with_stdio(false);
t = read();
while(t--){
solve();
}
}
F.
problem F
给定两个 \(multiset\), 只对其中一个集合的元素进行修改:
- \(x \rightarrow 2x\)
- \(x \rightarrow x/2\)
其中除以2是向下取整的。问能否通过这些操作把另一个集合变成和第一个集合一样。
思路: 不妨先将第一个集合的所有元素通通进行 \(/2\) 的操作只要 \(x\%2=0\),这样变成了一种 基元素。注意到此时的元素必然都是奇数,现在我们只需要采用操作2改变另一个集合即可,因为第一个操作只会使得元素变为偶数。
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<string>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
typedef long long ll;
using namespace std;
typedef unsigned long long int ull;
#define maxn 200005
#define ms(x) memset(x,0,sizeof(x))
#define Inf 0x7fffffff
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
#define pi acos(-1.0)
#define pii pair<int,int>
#define eps 1e-5
#define pll pair<ll,ll>
#define lson 2*x
#define rson 2*x+1
long long qupower(int a, int b) {
long long ans = 1;
while (b) {
if (b & 1)ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
inline int read() {
int an = 0, x = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') {
x = -1;
}
c = getchar();
}
while (c >= '0'&&c <= '9') {
an = an * 10 + c - '0'; c = getchar();
}
return an * x;
}
int t;
int n;
void solve(){
n = read();
multiset<int> a, b;
for(int i=0;i<n;i++){
int x = read();
while(x%2==0)x/=2;
a.insert(x);
}
for(int i=0;i<n;i++){
int x = read(); b.insert(x);
}
while(!b.empty()){
// max value of b
int x = *b.rbegin();
if(!a.count(x)){
// cannot find x
if(x==1) break;
b.erase(b.find(x));b.insert(x/2);
}
else{
// find x
a.erase(a.find(x)); b.erase(b.find(x));
}
}
if(b.empty()) printf("YES\n");
else printf("NO\n");
}
int main(){
//ios::sync_with_stdio(false);
t = read();
while(t--){
solve();
}
}