Codeforces Round 558(Div 2)题解

这场比赛没有打,后来和同学们一起开了场镜像打……

B是SB题结果WA了5发……

C是SB题结果差5min调出……虽然中间有个老师讲题吃掉了1h

D是比较神仙的题(2200),但是做出来了?算是比较超常发挥了。(平常能做出的题中最难的就是2200了)

E是2800,F是2900,zblzbl……

这次发挥还是不错的,写一篇题解吧。


A

首先发现在一个圆上删掉 $m$ 个点,段数的上界为 $m$。($0$ 除外,所以要特判 $0$)

然后剩下了 $n-m$ 个点。答案就是 $\min(m,n-m)$。

#include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<‘0‘ || ch>‘9‘) f|=ch==‘-‘,ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return f?-x:x;
}
int main(){
    int n=read(),m=read();
    if(!m) printf("%d\n",1);
    else printf("%d\n",min(m,n-m));
}


B1/B2

枚举 $k$ 看看可不可行。

与数出现次数有关,给数开个桶。

对于B1,直接大暴力讨论即可。

对于B2,对桶再开个同,就能优化暴力。

时间复杂度 $O(n)$。(细节太多了,就WA了5发……)

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010,mod=998244353;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<‘0‘ || ch>‘9‘) f|=ch==‘-‘,ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return f?-x:x;
}
int n,c1[maxn],c2[maxn],cnt,ans;
int main(){
    n=read();
    FOR(i,1,n){
        int w=read();
        c2[c1[w]]--;
        if(!c2[c1[w]]) cnt--;
        c1[w]++;
        c2[c1[w]]++;
        if(c2[c1[w]]==1) cnt++;
        if(cnt==1 && (c1[w]==1 || c2[c1[w]]==1) || (cnt==2 && (c2[c1[w]+1]==1 || c2[c1[w]]==1 && c2[c1[w]-1] || c2[1]==1))) ans=max(ans,i);
    }
    printf("%d\n",ans);
}


C1/C2

C1大暴力,没啥好说的。

C2反向考虑,斜率相同的直线对数。

记得去重。记得特判没有斜率($x$ 坐标相同)。

时间复杂度 $O(n^2\log n)$。(实现够好可以 $O(n^2)$?)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1010;
const double eps=1e-12;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<‘0‘ || ch>‘9‘) f|=ch==‘-‘,ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return f?-x:x;
}
struct line{
    double k,b;
    bool operator<(const line &l)const{
        if(fabs(k-l.k)>eps) return k<l.k;
        return b<l.b;
    }
    bool operator==(const line &l)const{
        return fabs(k-l.k)<eps && fabs(b-l.b)<eps;
    }
}l[maxn*maxn];
int n,x[maxn],y[maxn],m,cnt[20020],ccc;
ll ans;
int main(){
    n=read();
    FOR(i,1,n) x[i]=read(),y[i]=read();
    FOR(i,1,n) FOR(j,i+1,n){
        if(x[i]==x[j]){
            cnt[x[i]+10000]++;
            if(cnt[x[i]+10000]==1) ccc++;
            continue;
        }
        double k=1.0*(y[i]-y[j])/(x[i]-x[j]);
        l[++m]=(line){k,y[i]-k*x[i]};
    }
    sort(l+1,l+m+1);
    m=unique(l+1,l+m+1)-l-1;
    ans=1ll*m*(m-1)/2+1ll*m*ccc;
    for(int ll=1,rr;ll<=m;ll=rr+1){
        rr=ll;
        while(rr<=m && fabs(l[ll].k-l[rr].k)<eps) rr++;
        rr--;
        ans-=1ll*(rr-ll+1)*(rr-ll)/2;
    }
    cout<<ans<<endl;
}


D

考虑DP,$f[i][j][k]$ 表示 $c$ 的前 $i$ 个字符替换完了,$s$ 能匹配到前缀 $j$,$t$ 能匹配到前缀 $k$ 的最大值。

初始,$f[0][0][0]=0$,其他为 -INF。

转移,可以从 $f[i][j][k]$ 到 $f[i+1][j‘][k‘](0/+1/-1)$。后面的 $0/+1/-1$ 就要判断 $s$ 和 $t$ 是否可以匹配。

答案为 $\max(f[|c|][j][k])$。此时时间复杂度为 $O(|c||s|^3|t|^3|A|)$,优秀一点可以做到 $O(|c||s||t||A|+(|s|^3+|t|^3)|A|)$。(预处理 $to_s[i][c]$ 表示从 $s$ 的第 $i$ 个字符扩展一个 $c$ 最远能是哪个前缀,$t$ 类似)

此时已经可以通过本题,然而我SB没想到预处理 $to_s$,所以用了 KMP 优化找 $j‘$ 和 $k‘$。

时间复杂度 $O(|c||s||t||A|)$。

似乎可以用AC自动机或者讨论 $j$ 和 $k$ 的大小关系继续优化。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010,mod=998244353;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<‘0‘ || ch>‘9‘) f|=ch==‘-‘,ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return f?-x:x;
}
int l,n,m,f[maxn][55][55],nxts[55],nxtt[55],ans=-1e9;
char c[maxn],s[55],t[55];
void get_nxt(char s[],int l,int nxt[]){
    int j=0;
    FOR(i,2,l){
        while(j && s[i]!=s[j+1]) j=nxt[j];
        if(s[i]==s[j+1]) j++;
        nxt[i]=j;
    }
}
inline void chkmax(int &x,int y){if(y>x) x=y;}
void use(int i,int j,int k,char x){
    int jj=j,kk=k;
    while(jj && x!=s[jj+1]) jj=nxts[jj];
    if(x==s[jj+1]) jj++;
    while(kk && x!=t[kk+1]) kk=nxtt[kk];
    if(x==t[kk+1]) kk++;
    if(jj==n){
        if(kk==m) chkmax(f[i+1][nxts[n]][nxtt[m]],f[i][j][k]);
        else chkmax(f[i+1][nxts[n]][kk],f[i][j][k]+1);
    }
    else{
        if(kk==m) chkmax(f[i+1][jj][nxtt[m]],f[i][j][k]-1);
        else chkmax(f[i+1][jj][kk],f[i][j][k]);
    }
}
int main(){
    scanf("%s%s%s",c+1,s+1,t+1);
    l=strlen(c+1);n=strlen(s+1);m=strlen(t+1);
    get_nxt(s,n,nxts);
    get_nxt(t,m,nxtt);
    MEM(f,~0x3f);
    f[0][0][0]=0;
    FOR(i,0,l-1) FOR(j,0,n) FOR(k,0,m){
        if(c[i+1]!=‘*‘) use(i,j,k,c[i+1]);
        else FOR(x,‘a‘,‘z‘) use(i,j,k,x);
    }
    FOR(j,0,n) FOR(k,0,m) ans=max(ans,f[l][j][k]);
    printf("%d\n",ans);
}


E/F

会了再来填吧。

原文地址:https://www.cnblogs.com/1000Suns/p/10847629.html

时间: 2024-11-12 02:44:43

Codeforces Round 558(Div 2)题解的相关文章

Codeforces Round #262 (Div. 2) 题解

A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Vasya has n pairs of socks. In the morning of each day Vasya has to put on a pair of socks before he goes to school. When

Codeforces Round #FF (Div. 2) 题解

比赛链接:http://codeforces.com/contest/447 A. DZY Loves Hash time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output DZY has a hash table with p buckets, numbered from 0 to p?-?1. He wants to insert n 

Codeforces Round #259 (Div. 2) 题解

A. Little Pony and Crystal Mine time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Twilight Sparkle once got a crystal from the Crystal Mine. A crystal of size n (n is odd; n?>?1) is an n?×?n 

Codeforces Round #177 (Div. 2) 题解

[前言]咦?现在怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2.至于怎么决定场次嘛,一般我报一个数字A,随便再拉一个人选一个数字B.然后开始做第A^B场.如果觉得机密性不高,来点取模吧.然后今天做的这场少有的AK了.(其实模拟赛只做完了4题,最后1题来不及打了) 等等,话说前面几题不用写题解了?算了,让我难得风光一下啦. [A] A. Polo the Penguin and Segments time limit per test 2 seconds mem

Codeforces Round #534 (Div. 2)题解

Codeforces Round #534 (Div. 2)题解 A. Splitting into digits 题目大意 将一个数字分成几部分,几部分求和既是原数,问如何分可以使得分出来的各个数之间的差值尽可能小 解题思路 将n分成n个1相加即可 AC代码 #include<cstring> #include<string> #include<iostream> #include<cstdio> using namespace std; int main

Codeforces Round #561 (Div. 2) 题解

Codeforces Round #561 (Div. 2) 题解 题目链接 A. Silent Classroom 水题. Code #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 105; int n; char s[N], t[N]; int main() { cin >> n; for(int i = 1; i <= n; i++) { scanf(&q

Codeforces Round #608 (Div. 2) 题解

目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 程序 D. Portals 题意 做法 程序 E. Common Number 题意 做法 程序 结束语 Codeforces Round #608 (Div. 2) 题解 前言 题目链接:仅仅只是为了方便以题目作为关键字能查找到我的题解而已(逃 Codeforces 1271A Codeforce

Codeforces Round #617 (Div. 3) 题解

目录 Codeforces Round #617 (Div. 3) 题解 前言 A. Array with Odd Sum 题意 做法 程序 B. Food Buying 题意 做法 程序 C. Yet Another Walking Robot 题意 做法 程序 D. Fight with Monsters 题意 做法 程序 E1. String Coloring (easy version) 题意 做法 程序 E2. String Coloring (hard version) 题意 做法

[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F

[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F 1296A - Array with Odd Sum 思路: 如果一开始数组的sum和是奇数,那么直接YES, 否则:如果存在一个奇数和一个偶数,答案为YES,否则为NO 代码: int n; int a[maxn]; int main() { //freopen("D:\\code\\text\\input.txt","r",stdin); //freopen(