Codeforces Round #706 实录
【A】
就是把一段当成a_(k+1)删掉,剩下的构成回文串,其中一半长度>=k
另外删掉的长度不能为0,还有k=0的恶心情况,以及没及时跳出多输出的case。
又慌又乱,搞我心态,下一题。
【B】
S中的b会增加,当且仅当a=b+1(若a>b,a只能是b+1)
而一旦这种情况出现,以后的操作都是不断地加入最大值+1
那么下界如何变化呢?
对于S,假如里面没有0,b>0,那么似乎我们永远不会加入0到S中
没错。
那么每次加入的永远都会ceil((0+b)/2)。
启发我们思考初始a对后续加入数字的决定作用。
如果初始情况,分为两种a>b,a<b (a=b是不可能的)
如果a<b,那么ceil((a+b)/2)永远不会等于a,也<b,因此加入数字永远不变
如果a>b,即一开始讨论的情况。
就是简单的分类讨论,分析一下。
【C】
黄金矿工背景。n个矿工,y轴上。
没有原点钻石,n个钻石,x轴上。要求一一配对,最小化i距离和。
配对问题,总让我不得不想起什么逆序和乱序和的理论或者说贪心策略。
这里是两条线段,交叉的图像,让我想试试调整法。
最优方案的必要条件,包括不能被调整成功。这等价于
sqrt(x1^2+y1^2)
+
sqrt(x2^2+y2^2)
<=
sqrt(x1^2+y2^2)
+
sqrt(x2^2+y1^2)
根号总是扮演魔鬼的角色。
先溜了,看D题。
公式平方后整理得到
x1y2+x2y1<=x1y1+x2y2
而根据逆序乱序的知识。。(艹)
假设x1<x2,那么应该有y1>y2
于是这样匹配即可。
必要条件变为充分的构造条件。again。
查了一下,排序不等式不要求整数,OK。
但感觉这样算出来结果有点奇怪,还是根据对称性都取成绝对值吧。
哦不,
x1y2+x2y1<=x1y1+x2y2
每个数字都要平方。
但是,「必要条件变为充分的构造条件。again。」这是错的吧。
对于两个mienr和两个mine,它们或者普通配对或者交叉培养,可以这样处理。
但是如果一个mine在另一方案内压根不和这两个mienr的任一个匹配呢?
先不管之前的解法错在哪里。
从图像上,结合三角形的边不等式,不能出现交叉线段。
cin和printf混用,艹。
【D】
国人题啊。。
y!=x
博弈论?至少题面风格是这样的。
每次每人左移或者右移一个位置,但不能挤掉对方的位置,
且新的数字,对Q来说要递减,对D来说要递增。
看E题。
线性结构。
先考虑固定的初始x,y的最优方案。
这几把从哪儿开始入手啊。
p<=n,有意思。哦,p是全排列。
与相连的连续单调块有关。
Q一定不能选最大的p当x
也不能选两边都>它的p当x
Q和D不会互相穿梭。
如果Q走到D走过的位置,然后D这一轮成功应付了后,下一轮Q一定不能走。
对D来说,vice versa。
对于 > > 来说,Q不能选,否则D选它右边,Q第一回就挂
< < 同理,
> < 也不行。
x只能取< >
然后之后就是单向下降的过程。
假设x取了一个顶峰,其两坡(不包含峰)一个长为w1,另一个为w2
设w1>w2,那么y不能取w2上的点,否则会让x必胜。
如果w1是奇数,那么x必败,只要让y取谷底即可。
否则,x必胜。
似乎不管x或者y必然都取在长度最长的坡上(不一定只有一个)
如果这个长度是偶数(算上谷底和峰),那么x必败,否则必胜。
卧槽,似乎只有两边都是奇数才可以。
别忘了边界的时候也结算一遍对应的坡的长度,而不是只有转折的时候结算。
最后15s改完。
艹,还是WA。
卧槽,怎么交错题了,交给E了。
END. 实时rank两千多,爆炸啊。
【E】
在原图基础上挖空使得整体连通,且无环。求任意方案(不要求最小)
感觉是个找点结论利用的构造题(应该不是生成树这样的算法题吧)
想先做E,但是又被顺序吓到。
感觉是经典问题。
star图?
坐标系?象限?
或者一条竖边,其余横边?
两条横边不能连在一起。
标记点的行号不相邻的话,可以直接连横边。
否则,必然,间隔的跳行。
每行可以全取啊。
Go!
Wait,这样依然会可能成环。
Retreat。
要不要讨论别的东西,比如坐标和%4之类的。
【F】
没时间看了
【赛后订正】
【D】
首先,我们应该排除一种显然的情况,即最长坡的个数>2的情况,这种情况,y总是可以取一个x永远也无法走到的最长坡上,而x先走,先走完,先败。
如果最长坡只有一个,也不行,因为如果长度为偶数,y只要在这个谷底向上走,x不管是否迎面而走,都是输。如果长度为奇数,那么y只要取这个谷底上面一格,x不管是否迎面而走,都是输。
因此最长坡的数量只能等于2,并且共有一个顶峰(否则就可以按照最长坡个数>2的策略,让y走另一个x走不到的最长坡上开始走,x比败)(如果是共有一个谷底的话,x显然也输)
这种情况,只有坡长为奇数,x才可能赢。且只有这一个位置能赢。
我TM没有对最长坡的个数进行讨论,就差临门一脚啊
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,n) for (int i=1;i<=n;i++)
#define REP(i,a,b) for (int i=a;i<=b;i++)
#define pb push_back
#define fi first
#define se second
#define pi pair<int,int>
#define mp make_pair
typedef long long ll;
typedef complex<double> comp;
const int inf=0x3f3f3f3f;
const ll linf=1e18;
const int N=5e5+10;
const double eps=1e-10;
const ll mo=1e9+7;
int n;
int a[N];
int l;
int len1,len2;
int L[N],R[N];
int cnt,cnt2;
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n;
FOR(i,n) cin>>a[i];
FOR(i,n) {
if (i==1||a[i]>a[i-1]) {
l++;
} else {
L[i-1]=l;
l=1;
}
len1=max(len1,l);
}
L[n]=l;
l=0;
for (int i=n;i>=1;i--) {
if (i==n||a[i]>a[i+1]) {
l++;
} else {
R[i+1]=l;
l=1;
}
len2=max(len2,l);
}
R[1]=l;
int ans=max(len1,len2);
if (ans%2) {
FOR(i,n) if (L[i]==ans) cnt2++;
FOR(i,n) if (R[i]==ans) cnt2++;
FOR(i,n) {
if (L[i]&&R[i]) {
if (L[i]==ans&&R[i]==ans&&a[i]>a[i-1]&&a[i]>a[i+1]) {
cnt++;
}
}
}
if (cnt!=1||cnt2!=2) cout<<0<<endl;
else cout<<1<<endl;
} else cout<<0<<endl;
return 0;
}
【E】
的确是我之前的思路,把某些竖列都取遍,然后生长出横边来连接标记点。
之前没沿着这个思路深入干下去,是因为我发现两个横边会黏在一起构成环,即使间隔一行也可以因为间隔行中的两个标记点造成环,但是,如果间隔2行呢?
这就是正解。题面中的标记点互不相邻(甚至没有公共点,而不仅仅没有公共边!这一点是关键,赛场上我没读出这个意思)就导致了间隔2行不存在实现连通的两个相邻的标记点。
这样,每三列地分组,每一组中间列都取遍,那么这组的标记点必然成为连通块的子集。
接下来就是考虑组与组之间的连接。
我们只要,比如在组A 组B中,组A的第三列的第一个有标记点的位置和组B的第一列的第一个位置都取遍(或者反过来),就一定连通,也不会构成环(当然得先检验是否已经连通了,这种情况我们就什么也不做)
然后把这个做法,从3的倍数扩展到3k+1和3k+2上就行了 。
如果是3k+1,多出的一列,如果还没与前面的连通的话,把最上边第一个有点的位置和前面一组的对应位置给连通。
额,这不行,因为多出的一列,这组本身不一定连通,所以应该是某一行如果有连接的两个位置中有一个1,就对应两个位置都写上1.
如果是3k+2,似乎当成3k+3做也没区别。
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,n) for (int i=1;i<=n;i++)
#define REP(i,a,b) for (int i=a;i<=b;i++)
#define pb push_back
#define fi first
#define se second
#define pi pair<int,int>
#define mp make_pair
typedef long long ll;
typedef complex<double> comp;
const int inf=0x3f3f3f3f;
const ll linf=1e18;
const int N=5e5+10;
const double eps=1e-10;
const ll mo=1e9+7;
int t;
int n,m;
int a[600][600];
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>t;
while (t--) {
cin>>n>>m;
FOR(i,n) FOR(j,m) {
char c='\n';
while (c=='\n') cin>>c;
if (c=='X') a[i][j]=1;
else a[i][j]=0;
}
for (int j=2;j<=m;j+=3) {
FOR(i,n) a[i][j]=1;
if (j!=2) {
bool ok=0;
FOR(i,n) {
if (a[i][j-1]||a[i][j-2]) {
a[i][j-1]=a[i][j-2]=1;
ok=1;
break;
}
}
if (!ok) a[1][j-1]=a[1][j-2]=1;
}
}
if (m%3==1) {
int j=m;
FOR(i,n) {
if (a[i][j]) {
a[i][j]=a[i][j-1]=1;
}
}
}
if (m==1) {
FOR(i,n) a[i][1]=1;
}
FOR(i,n) {
FOR(j,m) if (a[i][j]) cout<<'X';
else cout<<'.';
cout<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号