Educational Codeforces Round 64部分题解
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部分题解的更多相关文章
- Educational Codeforces Round 64 部分题解
Educational Codeforces Round 64 部分题解 不更了不更了 CF1156D 0-1-Tree 有一棵树,边权都是0或1.定义点对\(x,y(x\neq y)\)合法当且仅当 ...
- Educational Codeforces Round 64 (Rated for Div. 2)题解
Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...
- Educational Codeforces Round 64(ECR64)
Educational Codeforces Round 64 CodeForces 1156A 题意:1代表圆,2代表正三角形,3代表正方形.给一个只含1,2,3的数列a,ai+1内接在ai内,求总 ...
- Educational Codeforces Round 63部分题解
Educational Codeforces Round 63 A 题目大意就不写了. 挺简单的,若果字符本来就单调不降,那么就不需要修改 否则找到第一次下降的位置和前面的换就好了. #include ...
- 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 ...
- Educational Codeforces Round 64 -C(二分)
题目链接:https://codeforces.com/contest/1156/problem/C 题意:给出n个数和整形数z,定义一对数为差>=z的数,且每个数最多和一个数组成对,求最多有多 ...
- Educational Codeforces Round 64 -B(贪心)
题目链接:https://codeforces.com/contest/1156/problem/B 题意:给一段字符串,通过变换顺序使得该字符串不包含为位置上相邻且在字母表上也相邻的情况,并输出. ...
- 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, ...
- Educational Codeforces Round 64 选做
感觉这场比赛题目质量挺高(A 全场最佳),难度也不小.虽然 unr 后就懒得打了. A. Inscribed Figures 题意 给你若干个图形,每个图形为三角形.圆形或正方形,第 \(i\) 个图 ...
随机推荐
- Spark in action on Kubernetes - Spark Operator的原理解析
前言 在上篇文章中,向大家介绍了如何使用Spark Operator在kubernetes集群上面提交一个计算作业.今天我们会继续使用上篇文章中搭建的Playground进行调试与解析,帮助大家更深入 ...
- 洛谷P2607 骑士
题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里, ...
- hdu4325 线段树 成段更新
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #def ...
- 重装系统后ORACLE数据库恢复的方法
如果我们的操作系统出现问题,重装系统后,ORACLE数据库应该如何恢复呢?下文就为您列举了两个重装系统后ORACLE数据库恢复的方法,供您参考. ORACLE数据库恢复的方法我们经常会用到,下面就为您 ...
- 折腾spring boot 应用
开发环境 安装配置java环境 配置maven环境,修改镜像地址 <mirror> <id>aliyunmaven</id> <mirrorOf>*&l ...
- JQ取消hover事件
$('a').unbind('mouseenter').unbind('mouseleave');
- hdu 1025 lis 注意细节!!!【dp】
感觉这道题浪费了我半个小时的生命......哇靠!原来输出里面当len=1时是road否则是roads!!! 其实做过hdu 1950就会发现这俩其实一样,就是求最长上升子序列.我用结构体记录要连线的 ...
- oralce CUBE
select id,area,stu_type,sum(score) score from students group by cube(id,area,stu_type) order by id,a ...
- SDUT-2130_数据结构实验之数组一:矩阵转置
数据结构实验之数组一:矩阵转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 数组--矩阵的转置 给定一个m*n的矩阵 ...
- This cache store does not support tagging.
用户权限管理系统 https://github.com/Zizaco/entrust 再添加角色的时候... 报了一个错.. BadMethodCallException in Repository. ...