Codeforces Round #549 (Div. 2) Solution
看懂题目就会写的题
给一个 $01$ 序列,找到最早的位置使得 $0$ 或 $1$ 已经全部出现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e6+;
int n,a[N];
int main()
{
n=read();
for(int i=;i<=n;i++) a[i]=read();
int t=n-; for(;t;t--) if(a[t]!=a[t+]) break;
printf("%d",t);
return ;
}
A
B.Nirvana
定义一个数的价值为它每一位的乘积,如 $132$ 的价值为 $1*3*2=6$ ,求所有小于等于 $n$ 的数中价值最大的数的价值
从后往前考虑每一位,贪心地想,这一位可以要取的值要么是此位的值,要么是 $9$,如果取此位的值就不会对后面有影响
如果取 $9$ 就相当于要往更高一位借 $1$
设 $f[i][0/1]$ 表示从后往前考虑到第 $i$ 位,此位向不向更高一位借 $1$
那么转移很好想,设此位的值为 $t$, $f[i][0]=max(f[i-1][0]*t,f[i-1][1]*(t-1))$
$f[i][1]=max(f[i-1][0]*9,f[i-1][1]*9)$
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline ll read()
{
ll x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
ll n,f[][];
int main()
{
n=read();
ll t=,cnt=;
while(t<=n) t*=,cnt++;
cnt--; t=n; f[][]=;
for(ll i=;i<=cnt;i++)
{
if(t%) f[i][]=max(f[i-][]*(t%),f[i-][]*(t%-));
f[i][]=max(f[i-][]*,f[i-][]*);
t/=;
}
cout<<max(f[cnt][],f[cnt-][]);//注意大一位可能被借没,所以要考虑小一位
return ;
}
B
C.Queen
给一颗树,有两种节点,一种不 '尊重' 所有祖先节点,一种 '尊重' 所有祖先节点
定义一次删除操作,删除一个不尊重祖先且没有 儿子 (不是后代)尊重的节点,如果有多个,取编号最小的节点删除
一个节点删除后,它的儿子全部接在此节点的父节点上,输出删除的顺序,如果没有节点被删除输出$-1$
找找性质,容易证明,如果一个节点刚开始不能删除,那么之后也不能删除(一直会有儿子尊重,或自己尊重祖先)
如果一个节点刚开始可以删除,那么之后一定会删除(儿子一定一直不尊重它,就算一个儿子删掉了,儿子的儿子也肯定不尊重祖先)
所以删除的节点一开始就可以确定,直接 $dfs$ 求出所有编号,然后排序输出
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+;
int n,rt;
bool p[N];
vector <int> V[N];
int tmp[N],tot;
bool dfs(int x)
{
bool flag=p[x];
for(int i=V[x].size()-;i>=;i--)
flag&=dfs(V[x][i]);
if(flag) tmp[++tot]=x;
return p[x];
}
int main()
{
int a; n=read();
for(int i=;i<=n;i++)
{
a=read(),p[i]=read();
if(a!=-) V[a].push_back(i);
else rt=i;
}
dfs(rt);
sort(tmp+,tmp+tot+);
if(!tot) { printf("-1"); return ; }
for(int i=;i<=tot;i++) printf("%d ",tmp[i]);
return ;
}
C
我原来题意一直没看懂啊...难怪不会写...
首先可以知道环的周长为 $S=n*k$
发现环是对称的,所以起点在哪个餐馆旁对答案没有影响,只要枚举终点在哪个餐馆旁,设 起点到终点的距离(同时也是步长)为 $L$,走的步数为 $stp$,那么就是要找到最小的 $t$ 使得 $S*t/L==stp$ 整除,此时 $S*t/L$ 就是步数,所以 $stp=S/gcd(L,S)$ ,然后就完了
注意起点和终点都分为在餐馆左边和右边两种情况
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
int n,K,A,B;
ll gcd (ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll Mi,Mx;
void solve(ll p)
{
ll s=1ll*n*K,pos,t,L,stp;
for(int i=;i<=n;i++)
{
pos=1ll*(i-)*K+;
t=pos-B; if(t<) t+=s;
L=t-p; if(L<) L+=s;
stp=s/gcd(s,L);
Mi=min(Mi,stp); Mx=max(Mx,stp);
t=pos+B; if(t>s) t-=s;
L=t-p; if(L<) L+=s;
stp=s/gcd(s,L);
Mi=min(Mi,stp); Mx=max(Mx,stp);
}
}
int main()
{
n=read(),K=read(),A=read(),B=read();
Mi=1ll*n*K;
solve(A+);
solve(K+-A);
cout<<Mi<<" "<<Mx<<endl;
return ;
}
D
给定一个排列和一个数列,多次询问,求数列区间 $l,r$ 中是否存在一个子序列(不是子串),使得此子序列经过循环移位后为给定的那个排列
定义一个序列的循环移位为 对于序列 $p[1],p[2]...p[n]$ 它的一个循环移位为 $p[k],p[k+1]...p[n]p[1]p[2]...p[k-1]$
考虑维护数列每个数在排列中的上一个数 上一次在数列中出现的位置 $pre$ ,贪心地想,要匹配一定是优先到最近的合法位置($pre$位置)
容易考虑对区间的每个数往前暴力走,如果走完 $n-1$ 步还在区间 $l,r$ 中则存在
如果每个数暴力走完发现都无解了,则不存在
考虑优化这个方法,发现我们暴力每次只跳一步,考虑直接预处理出暴力跳 $n-1$ 步时的位置,然后用$st$表维护一个区间的数跳 $n-1$ 步后的最大位置
如果最大位置大于等于 $l$ 则有解
发现还是不够,预处理每次只跳一步太慢了,考虑先维护倍增数组 $F[i][j]$ 表示位置 $i$ 跳 $2^j$ 步后到达的位置,这样预处理时只要跳 $log_n$ 次
然后就可以过了,复杂度 $O(nlog_n)$
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+;
int n,m,Q;
int A[N],B[N],pos[N],las[N],Log[N];
//A是排列,B是数列,pos[i]表示值i在排列中的位置,las动态维护一个数在数列中上一次出现的位置
int F[N][],G[N][];//F[i][j]是位置i跳2^j步后到达的位置,G[i][j]是ST表用来维护一个区间跳n-1步后到达的最右位置
int main()
{
n=read(),m=read(),Q=read();
for(int i=;i<=n;i++) A[i]=read(),pos[A[i]]=i;
for(int i=;i<=m;i++) B[i]=read();
for(int i=;i<=m;i++)
{
int t=A[ pos[B[i]]- ];
if(!t) t=A[n];//考虑循环置换
F[i][]=las[t]; las[B[i]]=i;
}
for(int i=;(<<i)<=n;i++)
for(int j=;j<=m;j++) F[j][i]=F[F[j][i-]][i-];//处理F
for(int i=;i<=m;i++)
{
int t=n-,p=i;
for(int j=;j>=;j--)
if(t-(<<j)>=) t-=(<<j),p=F[p][j];//跳n-1步
G[i][]=p;//处理G[i][0]
}
Log[]=-; for(int i=;i<=m;i++) Log[i]=Log[i>>]+;
for(int i=;(<<i)<=m;i++)
for(int j=;j+(<<i)-<=m;j++) G[j][i]=max(G[j][i-],G[j+(<<i-)][i-]);//维护G
while(Q--)
{
int l=read(),r=read();
int t=Log[r-l+];
if(max(G[l][t],G[r-(<<t)+][t])>=l) printf("");//处理询问
else printf("");
}
return ;
}
E
FU2
给一堆点,和一个抛物线 $y=x^2+bx+c$ ,显然把此抛物线代入任意两个横坐标不同的点可以确定它的形状
求有多少对点确定的抛物线中,没有任何点在它上方,如果有多组点确定的是同一条抛物线那么只算一次
发现这个二次项很恶心,如果给的是直线直接求上凸包就行了,考虑消掉二次项
把坐标进行变换 :$(x,y)-->(x,y-x^2)$,然后发现坐标系变换后原来的图像变成了直线
然后同样求上凸包就好了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
inline ll read()
{
ll x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+;
struct Poi{
ll x,y;
inline bool operator < (const Poi &tmp) const {
return x!=tmp.x ? x<tmp.x : y<tmp.y;
}
}p[N];
inline bool fc(Poi A,Poi B,Poi C) { return (B.y-A.y)*(C.x-A.x) >= (C.y-A.y)*(B.x-A.x); }
// 如果 (B.y-A.y)/(B.x-A.x)>=(C.y-A.y)/(C.x-A.x) 成立则返回1
int n,ans;
int st[N],Top;
int main()
{
n=read();
for(int i=;i<=n;i++)
{
p[i].x=read(); p[i].y=read();
p[i].y-=p[i].x*p[i].x;
}
sort(p+,p+n+);
st[Top=]=n;
for(int i=n-;i;i--)
{
while(Top> && fc(p[st[Top-]],p[st[Top]],p[i]) ) Top--;
st[++Top]=i;
}
for(int i=;i<=Top;i++) if(i==||p[st[i]].x!=p[st[i-]].x) ans++;
printf("%d",ans-);
return ;
}
F
Codeforces Round #549 (Div. 2) Solution的更多相关文章
- [题解] Codeforces Round #549 (Div. 2) B. Nirvana
Codeforces Round #549 (Div. 2) B. Nirvana [题目描述] B. Nirvana time limit per test1 second memory limit ...
- Codeforces Round #549 (Div. 1)
今天试图用typora写题解 真开心 参考 你会发现有很多都是参考的..zblzbl Codeforces Round #549 (Div. 1) 最近脑子不行啦 需要cf来缓解一下 A. The B ...
- Codeforces Round #466 (Div. 2) Solution
从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...
- 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution
对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...
- Codeforces Round #549 (Div. 2) 训练实录 (5/6)
The Doors +0 找出输入的01数列里,0或者1先出完的的下标. Nirvana +3 输入n,求1到n的数字,哪个数逐位相乘的积最大,输出最大积. 思路是按位比较,从低到高,依次把小位换成全 ...
- Codeforces Round #545 (Div. 1) Solution
人生第一场Div. 1 结果因为想D想太久不晓得Floyd判环法.C不会拆点.E想了个奇奇怪怪的set+堆+一堆乱七八糟的标记的贼难写的做法滚粗了qwq靠手速上分qwqqq A. Skyscraper ...
- [ Codeforces Round #549 (Div. 2)][D. The Beatles][exgcd]
https://codeforces.com/contest/1143/problem/D D. The Beatles time limit per test 1 second memory lim ...
- Codeforces Round 500 (Div 2) Solution
从这里开始 题目地址 瞎扯 Problem A Piles With Stones Problem B And Problem C Photo of The Sky Problem D Chemica ...
- Codeforces Round #549 (Div. 2) F 数形结合 + 凸包(新坑)
https://codeforces.com/contest/1143/problem/F 题意 有n条形如\(y=x^2+bx+c\)的抛物线,问有多少条抛物线上方没有其他抛物线的交点 题解 \(y ...
随机推荐
- JSSDK用法
参照微信官方文档,调试成功之后总结如下: 步骤一:绑定域名 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”. 备注:登录后可在“开发者中心”查看对应的接口权限. 步骤二: ...
- vmware 安装不成功导致的问题解决以及右键菜单添加打开终端命令
转自http://blog.csdn.net/puweilan/article/details/8609952 在VMware安装Ubuntu完成后,一直停留在VMware Easy Install, ...
- Inception安装
前言: MySQL语句需要审核,这一点每个DBA及开发人员都懂,但介于语句及环境的复杂性,大部分人都是望而却步,对其都是采取妥协的态度,从而每个公司都有自己的方法. 大多数公司基本都是半自动化(脚本+ ...
- c语言练习 二维数组 年平均降水量 月平均降水量
#define YEARS 5#define MONTHES 12 int main(void) { const float rain[YEARS][MONTHES] = { {4.3,4.3,4.3 ...
- JS获得css样式即获得元素的计算样式(《Javascript精粹修订版》书摘)
为HTML文档中的元素指定样式可以有3种方法:使用内嵌样式.在页面的head中对Style进行声明以及外部 CSS 文件.元素的视觉效果往往是由上述3种方式的结合或者其中某一种方式来确定的,但是内嵌样 ...
- (转)使用Jquery+EasyUI 进行框架项目开发案例讲解之四---组织机构管理源码分享
原文地址:http://www.cnblogs.com/huyong/p/3404647.html 在上三篇文章 <使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码 ...
- (转)对存储过程进行加密和解密(SQL 2008/SQL 2012)
原文地址:http://www.cnblogs.com/wghao/archive/2012/12/30/2837642.html 开始: 在网络上,看到有SQL Server 2000和SQL Se ...
- Schwartz kernel theorem施瓦兹核定理
In mathematics, the Schwartz kernel theorem is a foundational result in the theory of generalized fu ...
- [转]windows7远程桌面连接失败:发生身份验证错误。要求的函数不受支持
转至:https://jingyan.baidu.com/article/d169e18604ca86436611d821.html 系统升级后出现远程连接报错,“发生身份验证错误.要求的函数不受支持 ...
- [原创]Java中使用File类的list方法获取一定数量的文件:FilenameFilter接口的特殊用法
前言:有时候我们可能会遇到这样一个问题:需要遍历一个包含极多文件的文件夹,首先想到的肯定是使用File.list()方法,该方法返回一个String[],但是如果文件达到几亿呢?这个时候我们就需要分批 ...