Educational Codeforces Round 64部分题解

A

题目大意:给定三角形(高等于低的等腰),正方形,圆,在满足其高,边长,半径最大(保证在上一个图形的内部)的前提下.

判断交点个数是否有限,如果有限,输出.

很明显当正方形套三角形或者三角形套正方形是交点个数是无限的(因为有一条边相交)

其他图形的嵌套交点个数比较好判断,不多赘述

但是注意坑点:

当按照矩形,园,三角这样的顺序是,三角与圆的一个交点是与圆和正方形的交点重合的,判一下就好了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
using namespace std;
int n;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 - 48 + ch;
ch = getchar();
}
return v * c;
}
int a[312312];
bool flag = 1;
int ans;
int main(){
n = read();
for(int i = 1;i <= n;++i) a[i] = read();
for(int i = 2;i <= n;++i){
if(a[i] == 2 && a[i - 1] == 3) flag = 0;
if(a[i] == 3 && a[i - 1] == 2) flag = 0;
if(a[i] == 1){
if(a[i - 1] == 2) ans += 3;
if(a[i - 1] == 3) ans += 4;
}
if(a[i] == 2){
if(a[i - 1] == 1) ans += 3;
if(i > 2 && a[i - 2] == 3) ans--;
}
if(a[i] == 3 && a[i - 1] == 1){
ans += 4; }
}
if(flag) printf("Finite\n%d\n",ans);
else printf("Infinite\n");
return 0;
}

B

题目大意:给定一个字符串,将其重新排序,使得任意两个相邻的字母在字母表上不相邻(\(a\)与\(z\)不相邻)

这道题当时卡了幸好unrated

很明显,我们将奇数字符和偶数字符分开考虑,这样就保证了奇数之间和偶数之间不会出现上述情况,唯一需要考虑的就是奇数和偶数的交接部分.我们想,如果奇数的最后一个和偶数的第一个相接或者偶数的第一个和奇数的最后一个 相接都不能满足,那么就无解(因为我们这样已经尽可能地去保障了他们不会出现上述情况)

代码先咕一咕吧

C

题目大意:给定\(n\)(偶数)个数,将\(n\)个数分为\frac{n}{2}对,求一种方案,使得最多的点对\((i,j)\)满足\(|{a_i-a_j}|>=k\)

求一个\(nlogn\)的做法

很明显的一个错误贪心:

排序之后,对于每个\(a_i\),都找到他后面第一个\(a_j\)使得\(a_j-a_i>=k\),这些操作直接在\(multiset\)(我当时手写FHQ也是没谁了)上搞一搞就好了

但是,很明显是错的.

看下面一组数据

10 2

1 2 3 4 5 6 7 8 9 10答案为\(5\)

但是用上述方法答案是\(4\)

之后我们发现,我们排完序之后,答案最多为\(\frac{n}{2}\)(下取整),所以至少将前\(\frac{n}{2}\)个与后\(\frac{n}{2}\)个去匹配(很明显随着第一个指针右移,第二个也会右移),这个直接维护双指针,维护当前可用的最小的\(p\)就好了

#include<cstdio>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N = 2e5 + 3;
int a[N];
int n,k,ans;
int main(){
scanf("%d%d",&n,&k); int p = n / 2 + 1;
for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
sort(a + 1,a + n + 1);
for(int i = 1;i <= n / 2;++i){
for(;p <= n;++p)
if(a[p] - a[i] >= k) break; if(p > n) break;
ans++;p++;
}
printf("%d\n",ans);
return 0;
}

D

题目大意:给定一个边权为\(0/1\)的树,求出满足从\(x\)点到\(y\)点不会出现经过边权为\(1\)的边之后在经过边权为\(0\)的边的点对\((x,y)\)的个数

要求一个\(nlogn\)或者更优的算法

这道题听说可以用\(dsu\)去做,以后再学(flag)

我们考虑\(dp\)

设\(dp_{i,0/1}\)表示以\(i\)点为根时,只经过边权为\(0/1\)的边就到达\(i\)的点的个数

想一想,如果我们能够求出这个东西

那么

\(ans = \sum_{i = 1}^n dp_{i,0} * dp_{i,1} + dp_{i,0}+dp_{i,1}\)

所以难点在于计算出\(dp\)数组

先考虑在以\(i\)为根的子树中

很明显则有

\(dp_{i,w} = \sum_{j\in son_i}(dp_{j,w} + 1)\)

这样我们就可以求出在\(i\)的子树中的值了,但是我们想要的是其为根时候的\(dp\)值

那么我们进行第二遍\(dfs\),想一下

去推出由父亲到儿子的贡献

如果所有点到其父亲的路径是\(dp_{i,w}\)

那么到他自己也是\(dp_{i,w}\)(因为他们两个只有一条边的距离,且这条边的边权为\(w\))

在递归处理就好了

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#define mk make_pair
#define pii pair<int,int>
#define LL long long
using namespace std;
const int N = 2e5 + 3;
vector <pii> G[N];
LL f[N][2];
int n;
inline void dfs1(int x,int fa){
for(int i = 0;i < G[x].size();++i){
int y = G[x][i].first,z = G[x][i].second;
if(y == fa) continue;
dfs1(y,x);
f[x][z] += f[y][z] + 1;
}
}
inline void dfs2(int x,int fa){
for(int i = 0;i < G[x].size();++i){
int y = G[x][i].first,z = G[x][i].second;
if(y == fa) continue;
f[y][z] = f[x][z];
dfs2(y,x);
}
}
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 - 48 + ch;
ch = getchar();
}
return v * c;
}
int main(){
n = read();
for(int i = 1;i < n;++i){
int x = read(),y = read(),z = read();
G[x].push_back(mk(y,z));
G[y].push_back(mk(x,z));
}
dfs1(1,0);
dfs2(1,0);
LL ans = 0;
for(int i = 1;i <= n;++i)
ans += f[i][0] * f[i][1] + f[i][0] + f[i][1];
cout << ans << endl;
return 0;
}

E

题目大意,给定一个\(n\)的排列,求出满足\(a_l+a_r=\max_{i = l}^ra_i\)的区间\([l,r]\)的个数

我们直接寻找最大值去分治,数据随机的话,是可以\(nlogn\)的,但是就跟着\(noip2019 D1T1\)一样,如果每次最大值都靠向两边,复杂度是会退化为\(n^2\)的

之后我们想如果对于每个\(a_i\),我们都求出以其为最大值的区间的最大左右端点\(l_i,r_i\),之后我们设其到\(l_i\)的距离为\(L\),

到\(r_i\)的距离为\(R\),我们可以找到一个\(T(n) = T(L) + T(R) + n\)的做法,这个很明显没有进行优化.

但是,我们想一下,以\(a_i\)为最大值的区间端点必须在$l_i,r_i $之间,那么我们每次找到 $ L,R$中较小的一个去进行枚举.

之后查询\(a_i - a_j\)的位置是否在相反的一边,这样的话时间复杂度变成了\(nlog(n)\)了

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<deque>
#define LL long long
using namespace std;
const int N = 2e5 + 45;
int pos[N];
int a[N],l[N],r[N];
int n;
deque <int> q;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int main(){
n = read();
for(int i = 1;i <= n;++i) a[i] = read(),pos[a[i]] = i;
for(int i = 1;i <= n;++i){
while(!q.empty() && a[q.back()] < a[i]) q.pop_back();
l[i] = q.empty() ? 1 : q.back() + 1;
q.push_back(i);
}
q.clear();
for(int i = n;i >= 1;--i){
while(!q.empty() && a[q.back()] < a[i]) q.pop_back();
r[i] = q.empty() ? n : q.back() - 1;
q.push_back(i);
}
LL ans = 0;
// for(int i = 1;i <= n;++i) printf("%d %d\n",l[i],r[i]);
for(int i = 1;i <= n;++i){
// printf("a[i]:%d %d %d\n",a[i],l[i],r[i]);
if(i - l[i] < r[i] - i){
for(int j = l[i];j < i;++j)
if(pos[a[i] - a[j]] <= r[i] && pos[a[i] - a[j]] > i) ans++;
// printf("%d %d\n",j,pos[a[i] - a[l[i]]]);
}
else{
for(int j = r[i];j > i;--j){
if(pos[a[i] - a[j]] >= l[i] && pos[a[i] - a[j]] < i) ans++;
}
}
}
cout << ans << endl;
return 0;
}

Educational Codeforces Round 64部分题解的更多相关文章

  1. Educational Codeforces Round 64 部分题解

    Educational Codeforces Round 64 部分题解 不更了不更了 CF1156D 0-1-Tree 有一棵树,边权都是0或1.定义点对\(x,y(x\neq y)\)合法当且仅当 ...

  2. Educational Codeforces Round 64 (Rated for Div. 2)题解

    Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...

  3. Educational Codeforces Round 64(ECR64)

    Educational Codeforces Round 64 CodeForces 1156A 题意:1代表圆,2代表正三角形,3代表正方形.给一个只含1,2,3的数列a,ai+1内接在ai内,求总 ...

  4. Educational Codeforces Round 63部分题解

    Educational Codeforces Round 63 A 题目大意就不写了. 挺简单的,若果字符本来就单调不降,那么就不需要修改 否则找到第一次下降的位置和前面的换就好了. #include ...

  5. Educational Codeforces Round 64 (Rated for Div. 2) A,B,C,D,E,F

    比赛链接: https://codeforces.com/contest/1156 A. Inscribed Figures 题意: 给出$n(2\leq n\leq 100)$个数,只含有1,2,3 ...

  6. Educational Codeforces Round 64 -C(二分)

    题目链接:https://codeforces.com/contest/1156/problem/C 题意:给出n个数和整形数z,定义一对数为差>=z的数,且每个数最多和一个数组成对,求最多有多 ...

  7. Educational Codeforces Round 64 -B(贪心)

    题目链接:https://codeforces.com/contest/1156/problem/B 题意:给一段字符串,通过变换顺序使得该字符串不包含为位置上相邻且在字母表上也相邻的情况,并输出. ...

  8. Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

    题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l, ...

  9. Educational Codeforces Round 64 选做

    感觉这场比赛题目质量挺高(A 全场最佳),难度也不小.虽然 unr 后就懒得打了. A. Inscribed Figures 题意 给你若干个图形,每个图形为三角形.圆形或正方形,第 \(i\) 个图 ...

随机推荐

  1. 跟我一起认识axure(三)

    交互设置,添加链接 点击预览

  2. hdu2577 dp

    也可以字符串搞.dp思路还是很清晰的.dp[][0]表示未锁定,dp[][1]表示锁定键. #include<stdio.h> #include<string.h> #defi ...

  3. FastAdmin 开发第 4 天:初试命令行

    FastAdmin 最强大的是命令行 先从 test 表开始. 在 FastAdmin 默认有一个 test 表格,用于命令行 crud 测试. 如何开始? 只需要在项目命令行中输入以下命令就会自动生 ...

  4. python 六种典型的异常

  5. C++第一次作业(循环语句的使用)

    一.知识点 循环结构 二.教学目的 掌握while和do...while循环语句在C++中的写法 三.教学内容 1.while语句 (1)执行顺序:先判断表达式(循环控制条件)的值,若表达式的值为tr ...

  6. 一 linux安装python3

    参考 https://www.cnblogs.com/pyyu/p/7402145.html?tdsourcetag=s_pcqq_aiomsg 1 下载 网址:https://www.python. ...

  7. C# 从零开始写 SharpDx 应用 初始化dx修改颜色

    原文:C# 从零开始写 SharpDx 应用 初始化dx修改颜色 版权声明:博客已迁移到 https://blog.lindexi.com 欢迎访问.如果当前博客图片看不到,请到 https://bl ...

  8. SDUT-3344_数据结构实验之二叉树五:层序遍历

    数据结构实验之二叉树五:层序遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 已知一个按先序输入的字符序列,如abd ...

  9. js获取屏幕相关值

    <html><script>function a(){document.write("屏幕分辨率为:"+screen.width+"*" ...

  10. 解决pip is configured with locations that require TLS/SSL问题

    python3.7安装, 解决pip is configured with locations that require TLS/SSL问题1.安装相关依赖 yum install gcc libff ...