zoukankan      html  css  js  c++  java
  • 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
    ",1);
        else printf("%d
    ",min(m,n-m));
    }
    View Code

    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
    ",ans);
    }
    View Code

    C1/C2

    C1大暴力,没啥好说的。

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

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

    时间复杂度 $O(n^2log 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;
    }
    View Code

    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
    ",ans);
    }
    View Code

    E/F

    会了再来填吧。

  • 相关阅读:
    AutoCAD如何添加网络打印机 添加公司打印机
    AutoCAD如何方便截图放到Word文档,改成白底黑字
    AutoCAD如何倒角 倒圆角 倒直角
    [RxJS] Groupby operator
    [VSCode] Custom settings
    [TypeScript] Modifier
    [Javascript] Avoid Accidental Returns of New State by using the void Keyword
    动态创建选项卡
    eclipse运行内存不足解决办法
    使用jquery trigger 触发a标签的click事件取代window.open方法
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10847629.html
Copyright © 2011-2022 走看看