【codeforces】【比赛题解】#849 CF Round #431 (Div.2)
cf的比赛越来越有难度了……至少我做起来是这样。
先看看题目吧:点我。
这次比赛是北京时间21:35开始的,算是比较良心。
【A】奇数与结束
"奇数从哪里开始,又在哪里结束?梦想从何处起航,它们又是否会破灭呢?"
给定一个长度为n的序列。确定能不能将序列分成奇数个长度为奇数的非空字串,而且这其中每个子串以奇数开头,以奇数结尾。可以只分成一个(1也是奇数)。
输入
第一行一个正整数n,表示序列长度。
第二行n个整数,表示序列中的元素。
输出
输出"Yes"或"No"来表示能否做到把序列按要求分割。
样例输入1
5
1 0 1 5 1
样例输出1
Yes
样例输入2
4
3 9 9 3
样例输出2
No
题解
当时想了一个n²的DP,之后发现实在是太naive。
讲一下DP思路吧,用f1[i]表示能否将a[1...i]分割成奇数个奇数长度的子串,并且每个子串以奇数开头结尾,f2[i]表示能否分割成偶数个子串。
于是f1[i]=OR(f2[j] (a[j+1...i]长度为奇数并且以奇数开头结尾) ),f2[i]=OR(f1[j] (a[j+1...i]长度为奇数并且以奇数开头结尾) ).
特别的,f1[0]=false,f2[0]=true。
这种做法就可以过了,但是有更优秀的做法:
把序列分成奇数个奇数长度的序列,那么这个序列也是奇数长度的。偶数长度的直接No。
再考虑把序列分成两个以上的序列,那么最开始的序列的起始元素必须是奇数,最末尾的序列的结尾元素也必须是奇数。
这就对应了原序列的第一个与最后一个元素必须是奇数,而这时我们只分一段就好了。
就是说我们只需要判断n的奇偶,a[1]的奇偶和a[n]的奇偶就可以了。
程序:
#include <cstdio>
static const int MAXN = ; int n;
int a[MAXN]; int main()
{
scanf("%d", &n);
for (int i = ; i < n; ++i) scanf("%d", &a[i]); puts((n & ) && (a[] & ) && (a[n - ] & ) ? "Yes" : "No");
return ;
}
【B】
目前没做出来,调出来了再说自己的做法吧
先贴标程:
#include <bits/stdc++.h>
#define eps 1e-7
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,a[];
bool vis[];
bool check(double k,int b)
{
memset(vis,false,sizeof(vis));
int cnt=;
for (int i=;i<=n;i++)
{
if (a[i]-b==1LL*k*(i-))
{
vis[i]=true;
++cnt;
}
}
if (cnt==n) return false;
if (cnt==n-) return true;
int pos1=;
for (int i=;i<=n;i++)
if (!vis[i]&&pos1==) pos1=i;
for (int i=pos1+;i<=n;i++)
if (!vis[i])
{
if (fabs((double)(a[i]-a[pos1])/(i-pos1)-k)>eps) return false;
}
return true;
}
int main()
{
n=read();
for (int i=;i<=n;i++)
a[i]=read();
bool ans=false;
ans|=check(1.0*(a[]-a[]),a[]);
ans|=check(0.5*(a[]-a[]),a[]);
ans|=check(1.0*(a[]-a[]),a[]*-a[]);
if (ans) printf("Yes\n"); else printf("No\n");
return ;
}
【C】
题目都没看懂,真的很难受,这题挺难的。
标程:
#include <bits/stdc++.h> using namespace std; using ll = long long;
using ld = long double;
using D = double;
using uint = unsigned int;
template<typename T>
using pair2 = pair<T, T>; #ifdef WIN32
#define LLD "%I64d"
#else
#define LLD "%lld"
#endif #define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second int main()
{
int k;
scanf("%d", &k);
for (int i = ; i < ; i++)
{
int cnt = ;
while ((cnt + ) * cnt / <= k) cnt++;
k -= cnt * (cnt - ) / ;
for (int j = ; j < cnt; j++) printf("%c", 'a' + i);
}
return ;
}
"无论目标何在,无论遇见何人,让我们一同将这首歌传唱。"
在平面直角坐标系中,有一个长方形舞台,四角分别是(0,0),(0,h),(w,0),(w,h)。
可以看出在有任何人进入舞台之前,不会有任何碰撞发生。
在舞台的左边界和下边界站着一些舞者。分成两组:
①竖直:站在(xi,0)上,沿着y正方向前进(向上)。
②水平:站在(0,yi)上,沿着x正方向前进(向右)。
按照编舞指导,第i个舞者需要在前ti毫秒内站着不动,然后沿着指定方向以1单位/毫秒的速度前进,直到碰到舞台的边界为止。
当两个舞者碰撞时,她们会立刻改变各自的前进方向,然后继续沿着新的方向前进。
舞者们只要碰到了舞台的边界就会停止,请求出每个舞者最终停下的位置。
输入
第一行有三个数n,w,h。表示舞者数量,舞台的长宽。
接下来n行,每行三个数,gi,pi,ti,表示第i个舞者所在的组(gi=1:竖直组;gi=2:水平组),坐标位置(gi=1则pi=xi;gi=2则pi=yi)以及等待时间。
保证0<xi<w,0<yi<h。并保证没有两个舞者既在相同的组,还有相同的位置和等待时间。
输出
n行,每行两个数xi,yi。表示第i个舞者最终停在哪里。
样例输入1
8 10 8
1 1 10
1 4 13
1 7 1
1 8 2
2 2 0
2 5 14
2 6 0
2 6 1
样例输出1
4 8
10 5
8 8
10 6
10 2
1 8
7 8
10 6
样例输入2
3 2 3
1 1 2
2 1 1
1 1 5
样例输出2
1 3
2 1
1 3
数据范围及提示
1<=n<=100000,2<=w,h<=100000,1<=gi<=2,1<=pi<=99999,0<=ti<=100000。
对于样例数据1,这是对应的图:
对于样例数据2,没有舞者碰撞。
题解
很难的一题,不过我看来比C题简单……
注意到每个舞者出发后,每毫秒其坐标总是有一个加一,故(xi+yi)总是在增加。
而且我们发现,只有(xi+yi)相同的舞者才会碰撞。我们把(xi+yi)的值相同的舞者分在一起处理。
如何确定(xi+yi)的值呢??可以发现对于每个舞者,可以把(pi-ti)近似看做(xi+yi),(pi-ti)相同的舞者可能碰撞,而(pi-ti)不同的不可能碰撞。
我们对舞者按照(pi-ti)排序,处理出(pi-ti)相同的舞者。
对于(pi-ti)相同的舞者,我们如何处理呢?
试着把舞台斜过来看吧!让(0,0)在最下方,(w,h)在最顶端,(0,h)在左侧,(w,0)在最右侧。
这样,对于那些(pi-ti)相同的舞者,即出发后(xi+yi)相同的舞者们,她们在同一时间点必然处在同一水平线上。
并且每过一毫秒,她们向上走√2/2单位,向左或向右走√2/2单位。
这时候的碰撞要如何处理呢?
注意到在没有碰撞发生前,舞者从左到右的顺序是先是水平方向的舞者,坐标从大到小下来,然后是竖直方向的舞者,坐标从小到大往右走。
而所有碰撞都发生了之后呢??舞者的相对位置是不会改变的!原本在最左侧的舞者,仍然在左侧。舞者位置不会交换。
或者……这是另一种形式的交换了呢?注意到在水平方向坐标最大的舞者没有去到她本来应该去的位置,而是去了竖直方向第一个舞者应该去的位置。
是的,她们的位置交换了,但是这种交换很有规律,把舞者分成水平方向和竖直方向,那么水平方向的舞者按顺序要去到竖直方向的舞者按顺序应该去到的位置。依次推下来,就可以确定舞者最终的位置。我不太好解释这种方法的具体实现,先贴代码吧。
排序时要注意第一关键字是(pi-ti),第二关键字是先水平,后竖直,第三关键字是初始坐标,水平的从大到小,竖直的从小到大。
复杂度O(nlogn)
#include<cstdio>
#include<algorithm>
#include<cstring>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define F2(i,a,b) for(int i=a;i<b;++i)
int n,w,h,g[],p[],t[],I[],Ans[],Ansg[];
inline bool cmp(int x,int y){
if(p[x]-t[x]<p[y]-t[y]) return ;
else if(p[x]-t[x]>p[y]-t[y]) return ;
else{
if(g[x]>g[y]) return ;
else if(g[x]<g[y]) return ;
else{
if(g[x]==) return p[x]<p[y];
else return p[x]>p[y];
}
}
}
int main(){
scanf("%d%d%d",&n,&w,&h);
F(i,,n) scanf("%d%d%d",g+i,p+i,t+i),I[i]=i;
std::sort(I+,I+n+,cmp);
I[n+]=; p[]=; t[]=-;
int hor=,ver=;
F(i,,n){
if(g[I[i]]==) ++ver; else ++hor;
if(p[I[i]]-t[I[i]]!=p[I[i+]]-t[I[i+]]){
int j=i-hor-ver+, k=i-ver+,l,o;
for(l=k,o=j;l<=i;++l,++o)
Ans[I[o]]=p[I[l]],Ansg[I[o]]=g[I[l]];
for(;o<=i;++o,++j)
Ans[I[o]]=p[I[j]],Ansg[I[o]]=g[I[j]];
ver=hor=;
}
}
F(i,,n) if(Ansg[i]==) printf("%d %d\n",Ans[i],h); else printf("%d %d\n",w,Ans[i]);
return ;
}
【E】
没看题,以后再补吧。
【codeforces】【比赛题解】#849 CF Round #431 (Div.2)的更多相关文章
- 竞赛题解 - CF Round #524 Div.2
CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...
- CF Round #551 (Div. 2) D
CF Round #551 (Div. 2) D 链接 https://codeforces.com/contest/1153/problem/D 思路 不考虑赋值和贪心,考虑排名. 设\(dp_i\ ...
- CF Round #510 (Div. 2)
前言:没想到那么快就打了第二场,题目难度比CF Round #509 (Div. 2)这场要难些,不过我依旧菜,这场更是被\(D\)题卡了,最后\(C\)题都来不及敲了..最后才\(A\)了\(3\) ...
- CF Round #600 (Div 2) 解题报告(A~E)
CF Round #600 (Div 2) 解题报告(A~E) A:Single Push 采用差分的思想,让\(b-a=c\),然后观察\(c\)序列是不是一个满足要求的序列 #include< ...
- cf Round#273 Div.2
题目链接,点击一下 Round#273 Div.2 ================== problem A Initial Bet ================== 很简单,打了两三场的cf第一 ...
- 【codeforces】【比赛题解】#960 CF Round #474 (Div. 1 + Div. 2, combined)
终于打了一场CF,不知道为什么我会去打00:05的CF比赛…… 不管怎么样,这次打的很好!拿到了Div. 2选手中的第一名,成功上紫! 以后还要再接再厉! [A]Check the string 题意 ...
- 【codeforces】【比赛题解】#937 CF Round #467 (Div. 2)
没有参加,但是之后几天打了哦,第三场AK的CF比赛. CF大扫荡计划正在稳步进行. [A]Olympiad 题意: 给\(n\)个人颁奖,要满足: 至少有一个人拿奖. 如果得分为\(x\)的有奖,那么 ...
- 【codeforces】【比赛题解】#869 CF Round #439 (Div.2)
良心赛,虽然我迟了半小时233333. 比赛链接:#869. 呃,CF的比赛都是有背景的……上次是<哈利波特>,这次是<物语>…… [A]巧妙的替换 题意: Karen发现了石 ...
- 【codeforces】【比赛题解】#868 CF Round #438 (Div.1+Div.2)
这次是Div.1+Div.2,所以有7题. 因为时间较早,而且正好赶上训练,所以机房开黑做. 然而我们都只做了3题.:(. 链接. [A]声控解锁 题意: Arkady的宠物狗Mu-mu有一只手机.它 ...
随机推荐
- HDU2883_kebab
很好的题目. 有不多于200个任务,每个任务要在si到ei这个时间段内完成,每个任务的任务量是ti*ni,只有一台机器,且其单位时间内可完成的任务量为m. 现在问你,能否使所有的任务全部在规定的时间段 ...
- Python编写登陆接口
实现功能: 输入用户名和密码 认证成功后显示欢迎信息 输错三次后锁定 # 提示输入用户名和密码 # 验证用户名和密码 # 如果错误,则输出用户名或密码错误 # 如果成功,则输出 欢迎,XXX! #!/ ...
- c语言宏定义#define
1. 利用define来定义 数值宏常量 #define 宏定义是个演技非常高超的替身演员,但也会经常耍大牌的,所以我们用它要慎之又慎.它可以出现在代码的任何地方,从本行宏定义开始,以后的代码就就都认 ...
- Divisibility by 25 CodeForces - 988E(模拟)
遇见模拟题 有两种做法 例如这题: 1.直接去算次数(统计哪个数在第几位,然后去运算) 2.模拟操作 贴一个别人的代码...https://blog.csdn.net/weixin_39453270/ ...
- How Many Points? LightOJ - 1077(线段经过整点个数与gcd 证明)
题意: 已知两点 (x1,y1) 和 (x2, y2)求两点间线段上的整点的个数 解析: 就是求gcd(abs(x2- x1),abs(y2 - y1)) 证明: 我们分水平方向和竖直方向两个方向看 ...
- [UOJ391] 鸽举选仕
我把这题推荐给yyb让他把这题做它的T2他竟然不要QwQ....... 题目大意: 下发八个题目和对应的八份代码,请构造数据Hack下发代码. Task1 下发代码用了一些神奇做法实现A + B = ...
- 【2018ICPC青岛】
B 题意:给n个问题,每个问题有一个固定的答案ai(<=10^5).现在有m个约束关系,每个约束关系是一个二元组(ui,vi),表示你回答ui.vi问题的答案必须一样. 现在让你输出分别修复一个 ...
- BZOJ 1013 | 一份写了一堆注释的高斯消元题解
题意 给出\(n\)维直角坐标系中\(n + 1\)个点的坐标,它们都在一个\(n\)维球面上,求球心坐标. 题解 设球面上某两个点坐标为\((a_1, a_2, ... a_n)\)和\((b_1, ...
- Docker跟一般的虚拟机有什么区别
这是StackOverflow上的一个问题及其回答的翻译(原文:Docker.io跟一般的虚拟机有什么区别?).原文主要回答了三个问题: 1. Docker.io的基本原理是什么?2. 为什么在doc ...
- BZOJ2437 [Noi2011]兔兔与蛋蛋 【博弈论 + 二分图匹配】
题目链接 BZOJ2437 题解 和JSOI2014很像 只不过这题动态删点 如果我们把空位置看做\(X\)的话,就会发现我们走的路径是一个\(OX\)交错的路径 然后将图二分染色,当前点必胜,当且仅 ...