【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有一只手机.它 ...
随机推荐
- UVAlive4255_Guess
题目很好很有意思. 告诉你n个序列中,任意一个连续子序列的和与0相比较的结果. 构造一个满足条件的序列. 对于从x->y这一段的和,如果大于0,那么sum[x]>sum[y-1],显然我们 ...
- spring通过工厂模式解决页面耦合问题
spring通过工厂模式解决页面耦合问题
- 【HLSDK系列】overview(俯视图)
温馨提示:使用PC端浏览器阅读可获得最佳体验 阅读本文时,请时不时就对照参考图看一下. 什么是overview? 如果你有使用过3D模型制作工具,例如3dsMax等等,在编辑模型时这些软件通常会展示四 ...
- MT【145】不变的平面角
(2018,4月学考数学选择最后一题)如图,设矩形$ABCD$所在平面与梯形$ACEF$所在平面相交于$AC$. 若$AB=1,BC=\sqrt{3},AF=EF=EC=1,$则下面二面角的平面角为定 ...
- UILabel居中显示的方法
在IB中拖出一个UIView @IBOutlet weak var myView: UIView! 下面创建的UILabel是在myView中居中显示 方法1: var label = UILabel ...
- 【BZOJ2024】舞会(动态规划,容斥,高精度)
[BZOJ2024]舞会(动态规划,容斥,高精度) 题面 BZOJ 洛谷 题解 这种关系显然要先排序才不会不想影响. 设\(f[i][j]\)表示前\(i\)个女生中,选了\(j\)个女生配对,并且女 ...
- BZOJ4416 [Shoi2013]阶乘字符串 【序列自动机 + 状压dp】
题目链接 BZOJ4416 题解 建立序列自动机,即预处理数组\(nxt[i][j]\)表示\(i\)位置之后下一个\(j\)出现的位置 设\(f[i]\)表示合法字符集合为\(i\)的最短前缀,枚举 ...
- HDU--4705
题目: Y 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4705 分析:树形dp的思想,枚举中间点. #include<iostream> ...
- 洛谷P3201 [HNOI2009]梦幻布丁(链表 + 启发式合并)
题目链接 给出 \(n\) 个布丁,每个补丁都有其颜色.现在有 \(m\) 次操作,每次操作将第 \(x_i\) 种颜色全部变为第 \(y_i\) 种颜色. 操作中可能会插入询问,回答目前总共有多少段 ...
- D. Petya and Array 树状数组
题意: 给出一个数组,元素有正有负有0,问其区间和小于 t 的子区间的个数. sum[ r ]-sum[ l-1 ]<t,其中sum是a的前缀和. 实现的方法就是从前往后对于每一个sum[ i ...