Problem A:

题目大意:

给定两个数列\(a,b\),一次操作可以交换分别\(a,b\)数列中的任意一对数。求最少的交换次数使得任意一个数都在两个序列中出现相同的次数.

(\(1 \leq a_i,b_i \leq 5 , 1 \leq n \leq 100\))

题解:

直觉告诉我这么搞就行了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 128;
int a[maxn],b[maxn];
int numa[8],numb[8];
int main(){
int n;read(n);
for(int i=1;i<=n;++i) read(a[i]),numa[a[i]]++;
for(int i=1;i<=n;++i) read(b[i]),numb[b[i]]++;
int ans = 0;
for(int i=1;i<=5;++i){
if((numa[i] + numb[i]) % 2 == 1) return puts("-1");
ans += abs(numa[i] - numb[i])/2;
}printf("%d\n",ans>>1);
getchar();getchar();
return 0;
}

Problem B:

题目大意:

给定两个正整数n,k,求n最少的删除数码的次数使其可以被\(10^k\)整除.

题解:

直接删除后k位就好了,我居然栽在这道题上...

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
int main(){
string s;int k;
cin >> s >> k;
reverse(s.begin(),s.end());
int len = s.size();
int cnt1 = 0,cnt2 = 0;
for(int i=0;i<len;++i){
if(s[i] == '0') ++ cnt1;
else ++ cnt2;
if(cnt1 == k) break;
}
if(cnt1 == k) printf("%d\n",cnt2);
else printf("%d\n",len-1);
getchar();getchar();
return 0;
}

Problem C

题目大意:

有n个物品一定要购买,给出两个数组a,b分别表示这个星期和下个星期时物品的价值,规定这个星期必须买至少k件物品,求最小的代价买到所有物品.

题解:

首先我们在这个星期买掉所有的物品

然后我们到了下一个星期,如果发现有什么物品更便宜了

那么我们可以让时光倒流回上个星期,并且选择不在上个星期购买这个物品

至于k的限制吗。。。去价值差大于零的值中的前n-k大即可.

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
priority_queue<int> q;
const int maxn = 200010;
int a[maxn],b[maxn];
int main(){
int n,k;read(n);read(k);
ll sum=0;
for(int i=1;i<=n;++i) read(a[i]),sum+=a[i];
for(int i=1;i<=n;++i){
read(b[i]);
q.push(a[i]-b[i]);
}
for(int i=k+1;i<=n;++i){
if(q.top()>0) sum-=q.top(),q.pop();
}
printf("%I64d\n",sum);
getchar();getchar();
return 0;
}

Problem D

题目大意:

给定两个字符串S,T,设第一个字符串的长度为n,再给定一个{n}的排列。然后按照给定的排列依次删除S中对应位置上的字符.问第几次删除的时候T不再是S的子序列.

题解:

首先我们可以发现答案具有明显的单调性

所以我们二分答案

然后直接扫一遍两个串判定即可

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 200010;
char s1[maxn],s2[maxn];
int a[maxn],n,m;
bool vis[maxn];
inline bool check(int mid){
memset(vis,0,sizeof vis);
for(int i=1;i<=mid;++i){
vis[a[i]] = true;
}
int p1 = 1,p2 = 1;
while(p2 <= m && p1 <= n){
if(vis[p1]) ++ p1;
else{
if(s2[p2] == s1[p1]) ++p1,++p2;
else ++ p1;
}
}
if(p2 == m+1) return true;
return false;
}
int main(){
scanf("%s%s",s1+1,s2+1);
n = strlen(s1+1);
m = strlen(s2+1);
for(int i=1;i<=n;++i){
read(a[i]);
}
int l = 0,r = n,ans = -1;
while(l <= r){
int mid = (l+r) >> 1;
if(check(mid)) ans = mid,l = mid+1;
else r = mid-1;
}printf("%d\n",ans);
getchar();getchar();
return 0;
}

Problem E

题目大意:

给定一个只有赋值和二元位运算的程序,并且其中存在未知的变量'?',要求为所有的变量'?'确定一个相同的值.使程序结束后所有变量的和达到最值。

分别输出达到最大值和最小值时的'?'的值.

题解:

这是一道考码力的题啊。。。

分别枚举'?'的每个二进制位,下去计算变量之和即可

#include <map>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 5010;
map<string,int> mp;
char vari[maxn][maxn],va[maxn][maxn];
int typ[maxn],tmpx[maxn],tmpy[maxn],ans1[maxn],ans2[maxn];
char tmp[maxn],tt[maxn];
int n,m,val[maxn];
int work(int x,int t){
val[0] = t;
for(int i=1;i<=n;++i){
if(typ[i] == 0) val[i] = va[i][x] - '0';
else if(typ[i] == 1) val[i] = val[tmpx[i]] ^ val[tmpy[i]];
else if(typ[i]==2) val[i] = val[tmpx[i]] | val[tmpy[i]];
else val[i] = val[tmpx[i]] & val[tmpy[i]];
}int sum = 0;
for(int i=1;i<=n;++i) sum += val[i];
return sum;
}
int main(){
read(n);read(m);mp["?"] = 0;
for(int i=1;i<=n;++i){
scanf("%s",vari[i]);
scanf("%s%s",tt,va[i]+1);
mp[vari[i]]=i;
if(va[i][1] == '0'||va[i][1] == '1'){
typ[i] = 0;
continue;
}
tmpx[i] = mp[va[i]+1];
scanf("%s",tmp);
if(tmp[0] == 'X') typ[i] = 1;
else if(tmp[0] == 'O') typ[i] = 2;
else typ[i] = 3;
scanf("%s",va[i]+1);
tmpy[i] = mp[va[i]+1];
}
for(int i=1;i<=m;++i){
int sum1 = work(i,1);
int sum0 = work(i,0);
if(sum1 < sum0) ans1[i] = 1;else ans1[i]=0;
if(sum1 > sum0) ans2[i] = 1;else ans2[i] = 0;
}
for(int i=1;i<=m;++i) printf("%d",ans1[i]);puts("");
for(int i=1;i<=m;++i) printf("%d",ans2[i]);puts("");
getchar();getchar();
return 0;
}

Problem F

题目大意:

给定你一颗若干个串插入得到的Trie树,并且不存在任意一个串是另一个串的前缀.现在允许你删除所有长度>=k字符串的下标为k的字符,然后再把这些串插入到Trie中.确定一个尽量小的k使得后来得到的Trie的节点数目最少.(首先保证节点数目最少)

题解:

好长的题面...

我们发现其实就是让我们删除Trie树中的一层,然后把剩余的部分该合并的合并

使得最终的Trie的size最小,并且多解的情况下输出最小的k

我们其实可以直接计算出每一层如果删去了,那么会合并+删除多少个节点

然后我们遍历每一层取一个最大值即可

至于删去每一层时的计算,我们可以直接递归处理.

(比赛的时候没做出来就是因为只考虑了两层...)

其中有一个很关键的优化,如果遇到了一个点只有一个儿子的情况则直接退出

这样就保证了单次计算复杂度最高是\(logn\)的.

所以总复杂度\(O(nlogn)\)就可以AC了

现在想想自己当时比赛的时候真是傻了

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 300010;
int ch[maxn][27];
#define id(x) (x - 'a')
int dep[maxn],mxp,anss[maxn];
int get_num(const vector<int> &v){
int ret = v.size() - 1;
int n = v.size();
vector<int> vx;
for(int i='a';i<='z';++i){
vx.clear();
for(int j=0;j<n;++j){
if(ch[v[j]][id(i)]) vx.push_back(ch[v[j]][id(i)]);
}if(vx.size() <= 1) continue;
ret += get_num(vx);
}return ret;
}
void dfs(int u,int dep){
mxp = max(mxp,dep);
vector<int> v;
for(int i = 'a';i<= 'z';++i){
if(ch[u][id(i)]) v.push_back(ch[u][id(i)]);
}anss[dep] += get_num(v) + 1;
for(int i = 'a';i<= 'z';++i){
if(ch[u][id(i)]) dfs(ch[u][id(i)],dep+1);
}return;
}
int main(){
int n;read(n);
char c;
for(int i=1,u,v;i<n;++i){
read(u);read(v);while(c=getchar(),c<'!');
ch[u][id(c)] = v;
}dfs(1,1);
int ans = 0,ans_p = -1;
for(int i=1;i<=mxp;++i){
if(ans < anss[i]){
ans = anss[i];
ans_p = i;
}
}
printf("%d\n%d\n",n-ans,ans_p);
getchar();getchar();
return 0;
}

抽空去做做Div.1的D和E....

Codeforces Round #402 (Div. 2) 题解的更多相关文章

  1. Codeforces Round #182 (Div. 1)题解【ABCD】

    Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...

  2. Codeforces Round #402 (Div. 2)

    Codeforces Round #402 (Div. 2) A. 日常沙比提 #include<iostream> #include<cstdio> #include< ...

  3. Codeforces Round #402 (Div. 2) A+B+C+D

    Codeforces Round #402 (Div. 2) A. Pupils Redistribution 模拟大法好.两个数列分别含有n个数x(1<=x<=5) .现在要求交换一些数 ...

  4. Codeforces Round #608 (Div. 2) 题解

    目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...

  5. Codeforces Round #525 (Div. 2)题解

    Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...

  6. Codeforces Round #528 (Div. 2)题解

    Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...

  7. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  8. Codeforces Round #677 (Div. 3) 题解

    Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...

  9. Codeforces Round #665 (Div. 2) 题解

    Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...

随机推荐

  1. Jenkins maven仓库地址 和 手动修改maven 版本

    ① Jenkins maven仓库地址,一般情况会在:/root/.m2/repository/* ② 手动修改maven 版本,Apache 下载指定的maven版本,然后解压后copy到指定目录即 ...

  2. zookeepeer ID生成器 (一)

    目录 写在前面 1.1. ZK 的分布式命名服务 1.1.1. 分布式 ID 生成器的类型 UUID方案 1.1.2. ZK生成分布式ID 写在最后 疯狂创客圈 亿级流量 高并发IM 实战 系列 疯狂 ...

  3. 【python】-- 多进程的基本语法 、进程间数据交互与共享、进程锁和进程池的使用

    多进程 进程之间是相互独立的,python是启动进程的时候,是启动的是原生进程.进程是没有GIL锁的,而且不存在锁的概念,进程之间的数据式不能共享的,而线程是可以的. 1.进程的定义 用mulipro ...

  4. Android笔记之获取debug.keystore和release.keystore的MD5/SHA1值

    获取debug.keystore的key,如下图 获取release.keystore的key 输入命令keytool -list -v -keystore <jksFilename> 例 ...

  5. Android笔记之AsyncTask

    AsyncTask中的4个回调 onPreExecute(),在doInBackground(Params...)之前运行在UI线程中 onPostExecute(Result),在doInBackg ...

  6. 我的Android进阶之旅------> Android为TextView组件中显示的文本添加背景色

    通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...

  7. Linux中rpm包管理器

    包全名: 1.操作的包是没有安装的软件包时,使用全名,而且要注意路径 2.例如:jdk-8u131-linux-x64.rpm包名: 1.操作的是已经安装好的软件包,使用包名,是搜索/var/lib/ ...

  8. Android Message handling (based on KK4.4)

    一.几个关键概念 1.MessageQueue:是一种数据结构,见名知义,就是一个消息队列.存放消息的地方.每个线程最多仅仅能够拥有一个MessageQueue数据结构. 创建一个线程的时候,并不会自 ...

  9. C#使用SQL语句时候的万用密码问题

    实际上万用密码就是因为SQL里面的语句--是注释,利用bug添加用户名和密码. 例如,用户名为 adada’ or 1=1-- 第一个种写法登录成功了 第二种写法登录失败(正确) 第三种写法登录失败( ...

  10. 每天一个Linux命令(2)cd命令

    cd命令用来切换工作目录至dirname. 其中dirName表示法可为绝对路径或相对路径.若目录名称省略,则变换至使用者的home directory(也就是刚login时所在的目录).另外,~也表 ...