Codeforces Round #528 (Div. 1, based on Technocup 2019 Elimination Round 4) 自闭记

  整天自闭。

  A:有各种讨论方式。我按横坐标排了下然后讨论了下纵坐标单调和不单调两种情况。写了15min也就算了,谁能告诉我printf和cout输出不一样是咋回事啊?又调了10min啊?

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define int long long
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n;
struct data
{
    int x,y;
    bool operator <(const data&a) const
    {
        return x<a.x||x==a.x&&y<a.y;
    }
    bool operator ==(const data&a) const
    {
        return x==a.x&&y==a.y;
    }
}a[3],ans[1000000];
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    const char LL[]="%I64d\n";
#endif
    for (int i=0;i<3;i++) a[i].x=read(),a[i].y=read();
    sort(a,a+3);
    if (a[0].y<=a[1].y==a[1].y<=a[2].y)
    {
        for (int i=min(a[0].y,a[1].y);i<=max(a[0].y,a[1].y);i++) ans[++n].x=a[0].x,ans[n].y=i;
        for (int i=a[0].x;i<=a[1].x;i++) ans[++n].x=i,ans[n].y=a[1].y;
        for (int i=min(a[1].y,a[2].y);i<=max(a[1].y,a[2].y);i++) ans[++n].x=a[1].x,ans[n].y=i;
        for (int i=a[1].x;i<=a[2].x;i++) ans[++n].x=i,ans[n].y=a[2].y;
    }
    else
    {
        for (int i=a[0].x;i<=a[1].x;i++) ans[++n].x=i,ans[n].y=a[0].y;
        for (int i=min(a[1].y,a[0].y);i<=max(a[1].y,a[0].y);i++) ans[++n].x=a[1].x,ans[n].y=i;
        for (int i=min(a[0].y,a[2].y);i<=max(a[0].y,a[2].y);i++) ans[++n].x=a[1].x,ans[n].y=i;
        for (int i=a[1].x;i<=a[2].x;i++) ans[++n].x=i,ans[n].y=a[2].y;
    }
    sort(ans+1,ans+n+1);
    n=unique(ans+1,ans+n+1)-ans-1;
    cout<<n<<endl;
    for (int i=1;i<=n;i++) cout<<ans[i].x<<' '<<ans[i].y<<endl;
    return 0;
}
View Code

  B:将权值平均分在叶节点的边上即可。感性证明。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define int long long
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,p[N],t,degree[N];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    const char LL[]="%I64d\n";
#endif
    n=read(),m=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read();
        degree[x]++,degree[y]++;
    }
    if (n==2) {cout<<m;return 0;}
    int cnt=0;
    for (int i=1;i<=n;i++) if (degree[i]==1) cnt++;
    printf("%.8f",m*2.0/cnt);
    return 0;
}
View Code

  这个时候就40min了,简直垫底。

  C:考虑让置换后的串在不超过上界的前提下尽量大。一旦某一位不卡上界了,后面就只需要贪心地尽量满足下界。于是在每种字符第一次出现的位置考虑卡与不卡两种情况即可。简直是个思博题。但它是个码农题。不明白意义何在。写的丑的没边了。调了30min,最后3min过非常刺激。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define int long long
#define N 1000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int T,n,k,a[N],b[N],c[N],match[27],tmp[27];
char s[N];
bool used[27];
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    const char LL[]="%I64d\n";
#endif
    T=read();
    while (T--)
    {
        k=read();
        scanf("%s",s+1);n=strlen(s+1);
        for (int i=1;i<=n;i++) a[i]=s[i]-'a'+1;
        scanf("%s",s+1);
        for (int i=1;i<=n;i++) b[i]=s[i]-'a'+1;
        scanf("%s",s+1);
        for (int i=1;i<=n;i++) c[i]=s[i]-'a'+1;
        memset(match,0,sizeof(match));memset(used,0,sizeof(used));
        bool flag=0;
        for (int i=1;i<=n;i++)
        {
            if (!match[a[i]])
            {
                for (int x=c[i]-1;x>=1;x--)
                if (!used[x])
                {
                    for (int j=1;j<=k;j++) tmp[j]=match[j];
                    match[a[i]]=x;used[x]=1;
                    bool islim=1;flag=1;
                    for (int j=1;j<=n;j++)
                    {
                        if (match[a[j]]&&match[a[j]]>b[j]) islim=0;
                        if (islim&&match[a[j]]&&match[a[j]]<b[j]) {flag=0;break;}
                        if (!match[a[j]])
                        {
                            if (!islim)
                            {
                                for (int x=k;x>=1;x--)
                                if (!used[x]) {match[a[j]]=x,used[x]=1;break;}
                            }
                            else
                            {
                                bool f=1;
                                for (int x=k;x>=1;x--)
                                if (!used[x])
                                {
                                    if (x<b[j]) f=0;
                                    else match[a[j]]=x,used[x]=1,islim=x==b[j];
                                    break;
                                }
                                if (!f) {flag=0;break;}
                            }
                        }
                    }
                    if (flag) break;
                    memset(used,0,sizeof(used));
                    for (int j=1;j<=k;j++)
                    {
                        match[j]=tmp[j];
                        if (match[j]) used[match[j]]=1;
                    }
                    break;
                }
                if (flag) break;
                if (!used[c[i]]) match[a[i]]=c[i],used[c[i]]=1;
                else break;
            }
            if (match[a[i]]&&(match[a[i]]<c[i]||match[a[i]]==c[i]&&i==n))
            {
                //for (int j=1;j<=k;j++) tmp[j]=match[j];
                bool islim=1;flag=1;
                for (int j=1;j<=n;j++)
                {
                    if (match[a[j]]&&match[a[j]]>b[j]) islim=0;
                    if (islim&&match[a[j]]&&match[a[j]]<b[j]) {flag=0;break;}
                    if (!match[a[j]])
                    {
                        if (!islim)
                        {
                            for (int x=k;x>=1;x--)
                            if (!used[x]) {match[a[j]]=x,used[x]=1;break;}
                        }
                        else
                        {
                            bool f=1;
                            for (int x=k;x>=1;x--)
                            if (!used[x])
                            {
                                if (x<b[j]) f=0;
                                else match[a[j]]=x,used[x]=1,islim=x==b[j];
                                break;
                            }
                            if (!f) {flag=0;break;}
                        }
                    }
                }
                break;
                /*if (!flag)
                {
                    memset(used,0,sizeof(used));
                    for (int j=1;j<=k;j++)
                    {
                        match[j]=tmp[j];
                        if (match[j]) used[match[j]]=1;
                    }
                }*/
            }//��ȷ����ijλ������С�ڴ�ĵ����� 
            if (match[a[i]]&&match[a[i]]>c[i]) break;
            if (flag) break;
        }
        if (flag)
        {
            printf("YES\n");
            for (int i=1;i<=k;i++)
            if (!match[i])
            {
                for (int x=1;x<=k;x++)
                if (!used[x]) {match[i]=x,used[x]=1;break;}
            }
            for (int i=1;i<=k;i++) putchar(match[i]+'a'-1);printf("\n");
        }
        else printf("NO\n");
    }
    return 0;
}
View Code

  D:考虑什么样的人可能成为冠军。比如这个人出的是石头,那么显然要让出剪刀的尽量去消灭出布的,为了防止剪刀遇上石头又要尽量先让布去消灭其他出石头的。可以发现事实上不用管其他出石头的了,考虑一段石头区间,如果两端有出布的让出布的消灭掉即可,否则其两端都有剪刀,那么这段石头对剪刀没有任何影响。那么只要其两端都不是“有出布的但没有出剪刀的”就好了。现在要统计总共有多少人,对石头剪刀布各自算一遍,还是考虑石头,考虑把不合法的石头去掉,显然就是第一个布到第一个剪刀之间和最后一个剪刀到最后一个布之间的(有序)。这玩意好像也不难想而且怎么着也比C好写几倍吧?我能不能向天借个30min啊?

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define ll long long
#define int long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,tree[3][N],a[N];
char s[N];
int val(char c){if (c=='R') return 0;if (c=='P') return 1;if (c=='S') return 2;}
void add(int p,int k,int x){while (k<=n) tree[p][k]+=x,k+=k&-k;}
int query(int p,int k){int s=0;while (k) s+=tree[p][k],k-=k&-k;return s;}
set<int> q[3];
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    const char LL[]="%I64d\n";
#endif
    n=read(),m=read();
    scanf("%s",s+1);
    for (int i=1;i<=n;i++) add(a[i]=val(s[i]),i,1),q[val(s[i])].insert(i);
    for (int j=0;j<=m;j++)
    {
        if (j){int x=read(),y=val(getc());add(a[x],x,-1),add(y,x,1);q[a[x]].erase(x),a[x]=y,q[a[x]].insert(x);}
        int ans=0;
        for (int i=0;i<3;i++)
        {
            int sc=(i+2)%3,pp=(i+1)%3;
            if (q[pp].empty()) ans+=query(i,n);
            else if (q[sc].empty()) ;
            else
            {
                ans+=query(i,n);
                set<int>::iterator it=q[sc].begin();int x=*it;
                it=q[sc].end();it--;int y=*it;
                it=q[pp].begin();if ((*it)<x) ans-=query(i,x)-query(i,(*it));
                it=q[pp].end();it--;if ((*it)>y) ans-=query(i,(*it))-query(i,y);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

  我也不知道为什么还能涨分。result:rank 208 rating +7

猜你喜欢

转载自www.cnblogs.com/Gloid/p/10166615.html