Problem A. Neverending competitions

题目大意

一个团队有多个比赛,每次去比赛都会先订机票去比赛地点,然后再订机票返回.给出\(n\)个含有起止地点的购票记录(不按时间顺序),判断这个团队是否返回.

题解

竞速题

因为每次比赛都必定是一去一返

所以当订票记录个数为偶数的时候一定在家中,否则一定在比赛.

Code

a = input()
if a % 2 == 0:
print 'home'
else:
print 'contest'

Problem B. Code obfuscation

题目大意

在一个不同的词数目不超过26种且单个词长度>1的文档中,做如下替换:从前到后找出第一个长度>1的单词,并把所有这种单词替换成a,然后继续找..替换成b,继续..替换成c,继续...直到不存在这样的单词位置.然后删去所有的不可见字符构成一个字符串

现在给定一个字符串,判断这个字符串有没有可能是由上述替换得到的.

\(len \leq 500\)

题解

这个题面很长也不要怪我啊...

我们发现这样得到的字符串一定满足这样的一个性质:

若字母\(ch\)出现,那么\('a' .. (ch-1)\)一定都在之前就出现过了

所以我们应用这个性质直接判断即可.

Code

#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;
}
char s[512];
int main(){
scanf("%s",s+1);
int n = strlen(s+1);
int nw = 'a' - 1;
for(int i=1;i<=n;++i){
if(s[i] == nw+1) ++ nw;
if(s[i] > nw) return puts("NO");
}
puts("YES");
return 0;
}

Problem C. Table Tennis Game 2

题目大意

一场比赛结束当且仅当某一方的得分恰好为\(k\),现在给出若干场比赛后小M和小V的各场比赛得分之和,判断是否合法.若合法,则输出可能的最多比赛的

场数.\(k,a,b \leq 10^9\)

题解

设得分分别为\(sco_a,sco_b\)

我们知道合法时最多可能的比赛场数一定为\(\frac{sco_a}{k} + \frac{sco_b}{k}\)

那么现在问题就在于判定是否合法

我们知道如果一个局面不合法,一定是有某一方有余出来的无法解释来由的得分

例如\(k = 2,sco_1 = 1,sco_2 = 1\)

双方都无法解释得分的来由

但是如果有\(k = 2,sco_1 = 3,sco_2 = 1\)

\(sco_2\)就可以解释的通了

所以我们可以做如下判定

if( ( a < k && b % k) || (b < k && a % k) ) puts("-1");

Code

#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;
}
int main(){
int k,a,b;read(k);read(a);read(b);
if( ( a < k && b % k) || (b < k && a % k) ) puts("-1");
else printf("%d\n",a/k + b/k);
return 0;
}

Problem D. Artsem and Saunders

题目大意

定义\([n]\)表示集合\({1,2,..,n}\)给定函数\(f:[x]->[y]\)要求构造函数:\(g:[n]->[m]\)和\(h:[m]->[n]\)满足\(g(h(x)) = x,x \in [m]\)且\(h(g(x)) = f(x),x \in [n]\)。存在则输出,不存在输出-1.\((n \leq 10^5,m \leq 10^6)\)

题解

其实这道题就是让我们构建一系列的映射关系

我们发现要求\(g(h(x)) = x\)那么我们知道对于所有存在的\(h(x)\)

一定有\(g(h(x)) = x\),换句话说,如果我们知道了\(h(x)\)那么我们就知道\(g(h(x))\)

但是我们这样就直接确定了\(g(x)\)有可能(并且是大多数情况下)不满足\(g(h(x)) = x\)

我们想,在\(i,f(i)\)是什么情况的时候,有前式直接确定的\(g(x)\)满足后式

只有当\(i = f(i)\)的时候,我们可以令\(h(m) = i,g(i) = m\)

那么当\(i != f(i)\)呢,如果\(f(f(i)) = f(i)\)也就是我们映射到的元素所发出的映射已经被\(h(x),g(x)\)映射过了

那么我们就加一条\(g(i) = g(f(i))\)的映射就依然满足条件了。

如果\(f(f(i)) != f(i)\)那就无论如何都不可能有解了。

Code

#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 = 1000010;
int f[maxn],g[maxn],h[maxn];
int main(){
int n;read(n);
int m = 0;
for(int i=1;i<=n;++i){
read(f[i]);
if(f[i] == i){
h[++m] = i;
g[i] = m;
}
}
for(int i=1;i<=n;++i){
if(i != f[i]){
if(f[f[i]] != f[i]) return puts("-1");
else g[i] = g[f[i]];
}
}
printf("%d\n",m);
for(int i=1;i<=n;++i){
printf("%d",g[i]);
if(i != n) putchar(' ');
else putchar('\n');
}
for(int i=1;i<=m;++i){
printf("%d",h[i]);
if(i != m) putchar(' ');
else putchar('\n');
}
return 0;
}

Problem E. Tree Folding

题目大意

定义一种在树上的操作:选中树上的一条点数为奇数路径,取路径的中点,使左右两条路径剩余的点不含有除路径上的点的邻居。此时可以去掉两条路径中的一条路径(中点保留).问最后能否把这个树化成一条链.若能输出链的最小边数。\((n \leq 10^5)\)

题解

题目是个谜

读了半天才读懂。。。

其实就是选择一个点,然后若这个点的两个子树是长度相同的链

就可以消掉两个子树中的一个

我们发现所有长度相同的是链的子树一定能合并

而且这道题很好dp,于是我们使用树形dp来解决这个问题

自底向上更新时,首先我们知道所有的子树都必须转化成链,这样答案才有可能

转化成链的充要条件是子树的链只有一种长度,因为有两种长度及以上就要分叉了

不过如果只有两种长度的话,那么这个点作为根也是可能可行的,于是我们需要找到一个这样的点尝试使其作为根.

而如果有两种以上的长度的话就不用想了,问题无解。

如果只有一种长度的话我们就直接将长度+1然后向上更新即可

对于长度的判重本来写了个Hash_map的,结果炸了,改成了set..

Code

#include <set>
#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 = 200010;
struct Edge{
int to,next;
}G[maxn<<1];
int head[maxn],cnt;
void add(int u,int v){
G[++cnt].to = v;
G[cnt].next = head[u];
head[u] = cnt;
}
inline void insert(int u,int v){
add(u,v);add(v,u);
}
int rt = 1,rec;
bool flag = false;
#define v G[i].to
int dfs(int u,int f){
set<int>s;
for(int i = head[u];i;i=G[i].next){
if(v == f) continue;
int x = dfs(v,u);
if(x == -1) return -1;
s.insert(x+1);
}
if( (s.size() == 2 && f) ){rt = u;return -1;}
if( s.size() > 2 ){flag = true;return -1;}
if(s.size() == 0) return 0;
set<int>::iterator it = s.begin();
int x = *it;
if(s.size() == 1) return x;
return x + (*(++it));
}
#undef v
int main(){
int n;read(n);
for(int i=1,u,v;i<n;++i){
read(u);read(v);
insert(u,v);
}
int ans = dfs(1,0);
if(flag) return puts("-1");
flag = false;rec = rt;
if(rt != 1) ans = dfs(rt,0);
if(flag || rec != rt) return puts("-1");
while(ans && !(ans&1)) ans >>= 1;
printf("%d\n",ans);
getchar();getchar();
return 0;
}

Problem F. Souvenirs

题目大意

给定一个长为\(n\)的序列,每次询问区间\([l,r]\)内的任意两个元素的最小的_差值的绝对值_.\((n \leq 10^5,m \leq 3*10^5)\)

题解

这道题我想了不少做法.

algorithm 1:

使用一颗线段树来维护区间内最小元素差

向上更新时使用归并排序的方式合并.(这好像叫做划分树)

预处理没有问题,问题在于查询的时候无法简单合并区间...

所以在查询的时候考虑使用std::set来解决这个东西

利用set进行启发式合并可以做到\(O(mlog^3n)\)

做点底层优化应该能过@WC2017的某松

algorithm 2:

我们仍然使用一颗线段树来维护区间内的最小元素差

但是我们先不统计出所有的答案

只在线段树的节点内存上某个点代表的区间所包含的所有元素

我们将所有的询问按第一关键字为l,第二关键字为r排序

然后我们从序列右端点开始向左扫描

依次考虑每个点对这个点到序列端点的区间所造成的影响

每次处理影响我们就类比于线段树的区间修改操作

修改线段树上每个节点内存储的最小元素差

但是这样我们就发现:现在线段树中的点已经不满足初始的定义了

因为对于所有的线段树中的点所代表的左区间其实都变成了当前扫描线所在的位置

这恰恰是我们对于询问排序的目的。

我们发现,在这种顺序下的询问中,上述错误不会带来任何影响

只要我们在扫描线扫描到某一个点的左端点的时候立即查询即可

因为右边界仍是满足的。

然后你需要一个set来剪枝加速,不然会Time limit exceeded on test 7

Code

#include <set>
#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 = 100010;
const int maxm = 300010;
int minn[maxn<<2];
int tmp[maxn],a[maxn];
int L,R,val,nw_min,n;
set<int>T[maxn<<2];
void build(int rt,int l,int r){
minn[rt] = 0x7f7f7f7f;
for(int i=l;i<=r;++i) T[rt].insert(a[i]);
if(l == r) return;
int mid = l+r >> 1;
build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
}
int query(int rt,int l,int r){
if(L <= l && r <= R) return minn[rt];
int mid = l+r >> 1;
if(R <= mid) return query(rt<<1,l,mid);
if(L > mid) return query(rt<<1|1,mid+1,r);
return min(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
}
inline bool exit_it(int rt){
set<int>::iterator it = T[rt].lower_bound(val);
int y = it == T[rt].end() ? -1 : *it;
int x = -1;
if(it != T[rt].begin()) x = *(--it);
if( (y == -1 || abs(y-val) >= nw_min) && (x == -1 || (abs(x-val) >= nw_min) ) ){
nw_min = min(nw_min,minn[rt]);
return true;
}return false;
}
void cacu(int rt,int l,int r){
if(l == r){
minn[rt] = min(minn[rt],abs(val - a[l]));
nw_min = min(nw_min,minn[rt]);
return ;
}
if(exit_it(rt)) return;
int mid = l+r >> 1;
if(L <= mid) cacu(rt<<1,l,mid);
if(R > mid) cacu(rt<<1|1,mid+1,r);
minn[rt] = min(minn[rt<<1],minn[rt<<1|1]);
}
struct Node{
int l,r,id;
bool friend operator < (const Node &a,const Node &b){
return !(a.l == b.l ? a.r < b.r : a.l < b.l );
}
}q[maxm];
int anss[maxm];
int main(){
read(n);
for(int i=1;i<=n;++i) read(a[i]);
int m;read(m);
build(1,1,n);
for(int i=1;i<=m;++i){
read(q[i].l);read(q[i].r);
q[i].id = i;
}sort(q+1,q+m+1);
for(int i=1,p=n;i<=m;++i){
while(p >= q[i].l){
L = p+1;R = n;val = a[p];nw_min = 0x7f7f7f7f;
if(L <= R) cacu(1,1,n);
--p;
}
L = q[i].l;R = q[i].r;
anss[q[i].id] = query(1,1,n);
}
for(int i=1;i<=m;++i) printf("%d\n",anss[i]);
getchar();getchar();
return 0;
}

Problem G. Math, math everywhere

这道题实在不会...

orz做出来的大爷们

#include <set>
#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;
}
int main(){
while(1) printf("orz\n");
getchar();getchar();
return 0;
}

Codeforces Round #397 题解的更多相关文章

  1. Codeforces Round #556 题解

    Codeforces Round #556 题解 Div.2 A Stock Arbitraging 傻逼题 Div.2 B Tiling Challenge 傻逼题 Div.1 A Prefix S ...

  2. Codeforces Round #569 题解

    Codeforces Round #569 题解 CF1179A Valeriy and Deque 有一个双端队列,每次取队首两个值,将较小值移动到队尾,较大值位置不变.多组询问求第\(m\)次操作 ...

  3. Codeforces Round #557 题解【更完了】

    Codeforces Round #557 题解 掉分快乐 CF1161A Hide and Seek Alice和Bob在玩捉♂迷♂藏,有\(n\)个格子,Bob会检查\(k\)次,第\(i\)次检 ...

  4. CFEducational Codeforces Round 66题解报告

    CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第 ...

  5. Codeforces Round #542 题解

    Codeforces Round #542 abstract I决策中的独立性, II联通块染色板子 IIIVoronoi diagram O(N^2 logN) VI环上距离分类讨论加取模,最值中的 ...

  6. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) F. Souvenirs 线段树套set

    F. Souvenirs 题目连接: http://codeforces.com/contest/765/problem/F Description Artsem is on vacation and ...

  7. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding 拓扑排序

    E. Tree Folding 题目连接: http://codeforces.com/contest/765/problem/E Description Vanya wants to minimiz ...

  8. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) D. Artsem and Saunders 数学 构造

    D. Artsem and Saunders 题目连接: http://codeforces.com/contest/765/problem/D Description Artsem has a fr ...

  9. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) C. Table Tennis Game 2 水题

    C. Table Tennis Game 2 题目连接: http://codeforces.com/contest/765/problem/C Description Misha and Vanya ...

随机推荐

  1. java中url正则regex匹配

    String regex = "^(?:https?://)?[\\w]{1,}(?:\\.?[\\w]{1,})+[\\w-_/?&=#%:]*$"; 解释说明: ^ : ...

  2. Linux模块机制浅析_转

    Linux模块机制浅析 转自:http://www.cnblogs.com/fanzhidongyzby/p/3730131.htmlLinux允许用户通过插入模块,实现干预内核的目的.一直以来,对l ...

  3. CString 成员函数用法大全(转)

    CString( );例:CString csStr; CString( const CString& stringSrc );例:CString csStr("ABCDEF中文12 ...

  4. React中key的必要性与使用

    React这个框架的核心思想是,将页面分割成一个个组件,一个组件还可能嵌套更小的组件,每个组件有自己的数据(属性/状态);当某个组件的数据发生变化时,更新该组件部分的视图.更新的过程是由数据驱动的,新 ...

  5. php字符串中 转义字符 “ ’‘ ” ’ “” ‘ " \’ ' ' \‘ " " \" '' \ " " 使用

    <?php echo $str_string1='甲问:"你在哪里学的PHP?"'; echo "<br />"; echo $str_str ...

  6. android菜鸟学习笔记5----第一个android程序

    程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...

  7. net上传文件的三种方法

    ASP.NET依托.net framework类库,封装了大量的功能,使得上传文件非常简单,主要有以下三种基本方法. 方法一:用Web控件FileUpload,上传到网站根目录. Test.aspx关 ...

  8. 九度OJ 1015:还是A+B (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6773 解决:4031 题目描述: 读入两个小于10000的正整数A和B,计算A+B.需要注意的是:如果A和B的末尾K(不超过8)位数字相同 ...

  9. centos 安装postgresql 完整版

    按步骤 执行命令即可: yum install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-c ...

  10. Eclipse中servlet显示无法导入javax.servlet包问题的解决方案

    项目名-->右键 Property-->选择 JavaBuild Path-->选择 Add External JARs-->选择 把servlet-api.jar的路径输入即 ...