Codeforces Round #438 (Div. 1 + Div. 2 combined)(除G)解题报告

来源:互联网 发布:c语言库函数大全 chm 编辑:程序博客网 时间:2024/06/06 10:41

这场梁大大怎么就用我小号打了啊??
然后就2个小时出场?然后rank15涨飞?
(dlsFST好惨啊)

Bark to Unlock

搞笑题,记得考虑原来就出现就不会FST。

#include <bits/stdc++.h>#define gc getchar()#define ll long longusing namespace std;char a[2],b[2];int n,num[1000][2];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    a[0]=gc,a[1]=gc;    n=read();    for (int i=1;i<=n;i++)    {        while (b[0]=gc,b[0]<'a'||b[0]>'z');        b[1]=gc;        if (b[0]==a[0]&&b[1]==a[1])        {            puts("YES");            return 0;        }        num[b[0]][0]++,num[b[1]][1]++;    }    if (num[a[0]][1]&&num[a[1]][0]) puts("YES");    else puts("NO");    return 0;}

Race Against Time

一百种方法的题目。

#include <bits/stdc++.h>#define gc getchar()#define ll long longusing namespace std;double a[3];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    int h,m,s,t1,t2;    h=read(),m=read(),s=read(),t1=read(),t2=read();    a[0]=(double)(h%12)+(double)m/60.0+(double)s/3600.0;    a[1]=(double)m/5.0+(double)s/300.0;    a[2]=(double)s/5.0;    sort(a,a+3);    if (t1>a[0]&&t1<a[1])    {        if (t2>a[0]&&t2<a[1]) puts("YES");        else puts("NO");    }    if (t1>a[1]&&t1<a[2])    {        if (t2>a[1]&&t2<a[2]) puts("YES");        else puts("NO");    }    if (t1<a[0]||t1>a[2])    {        if (t2<a[0]||t2>a[2]) puts("YES");        else puts("NO");    }    return 0;}

Qualification Rounds

似乎总共就最多16种。dfs似乎就好了。(小猫代码)

#include <bits/stdc++.h>#define gc getchar()#define ll long longusing namespace std;int f[2][2][2][2],n,k,a[5],u[5],v[5],flag;void dfs(int x){    if (x==5)    {        if (f[u[1]][u[2]][u[3]][u[4]]&&f[v[1]][v[2]][v[3]][v[4]])            flag=1;        return;    }    for (int i=0;i<=1;i++)        for (int j=0;j<=1;j++)            if (i+j!=2)            {                u[x]=i,v[x]=j;                dfs(x+1);            }}int main(){    scanf("%d%d",&n,&k);    for (int i=1;i<=n;i++)    {        for (int j=1;j<=4;j++)        {            if (j<=k) scanf("%d",&a[j]);            else a[j]=0;        }        f[a[1]][a[2]][a[3]][a[4]]=1;    }    dfs(1);    puts(flag?"YES":"NO");}

Huge Strings

答案最多8(应该挺好证)。然后就只要维护前后8个就好。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 109#define M 8using namespace std;bitset<1<<M> pd[N<<1][M+1];int n,m,l[N<<1][M+1],r[N<<1][M+1],len[N<<1],b[N],ret;char str[N];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    n=read();    for (int i=1;i<=n;i++)    {        scanf("%s",str+1);        len[i]=strlen(str+1);        for (int j=1;j<=M;j++)        {            if (len[i]<j) break;            int now=0;            for (int k=1;k<j;k++) now=now<<1|(str[k]-'0');            for (int k=j;k<=len[i];k++)            {                now=(now<<1|(str[k]-'0'))&((1<<j)-1);                pd[i][j][now]=1;            }        }        for (int j=1;j<=min(len[i],M);j++)            l[i][j]=(str[j]-'0'),r[i][j]=(str[len[i]-j+1]-'0');    }    m=read();    while (m--)    {        int x=read(),y=read(),L=0;        for (int j=min(len[x],M);j;j--)            b[++L]=r[x][j];        for (int j=1;j<=min(len[y],M);j++)            b[++L]=l[y][j];        assert(L<=2*M);        len[++n]=len[x]+len[y],ret=0;        if (len[x]>M||len[y]>M||len[n]>M) len[n]=M+1;        if (len[n]<=M)            for (int i=1;i<=L;i++)                l[n][i]=b[i],r[n][i]=b[L-i+1];        else        {            for (int i=1;i<=min(len[x],M);i++)                l[n][i]=l[x][i];            if (len[x]<M)                for (int i=len[x]+1;i<=M;i++)                    l[n][i]=l[y][i-len[x]];            for (int i=1;i<=min(len[y],M);i++)                r[n][i]=r[y][i];            if (len[y]<M)                for (int i=len[y]+1;i<=M;i++)                    r[n][i]=r[x][i-len[y]];        }        for (int i=1;i<=M;i++)        {            pd[n][i]=pd[x][i]|pd[y][i];            if (L<i) continue;            int now=0;            for (int k=1;k<i;k++) now=now<<1|b[k];            for (int k=i;k<=L;k++)            {                now=(now<<1|b[k])&((1<<i)-1);                assert(now<(1<<i));                pd[n][i][now]=1;            }        }        for (int i=1;i<=M;i++)        {            bool flag=((int)pd[n][i].count()==(1<<i));            if (flag) ret=i;            else break;        }        printf("%d\n",ret);    }    return 0;}

Policeman and a Tree

dp[x][y][z][w]表示从y走到xy这边剩下z个点,x这边剩下w个点的最短距离,枚举第一条边,记忆化搜索即可。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 59#define inf 0x3f3f3f3fusing namespace std;int n,first[N],number,st,tg[N],m,fa[N],d[N],f[N][N];int DP[N][N][N][N],Ans=inf;struct edge{    int to,next,val;    void add(int x,int y,int z)    {        to=y,next=first[x],first[x]=number,val=z;    }}e[N<<1];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int dp(int x,int y,int z,int w){    if (z==0&&w==0) return 0;    if (DP[x][y][z][w]) return DP[x][y][z][w];    if (d[x]==1)    {        if (z==0) return 0;        return DP[x][y][z][w]=dp(y,x,0,z)+f[x][y];    }    int g[N];    for (int i=1;i<=w;i++) g[i]=-inf;    g[0]=inf;    for (int i=first[x];i;i=e[i].next)        if (e[i].to!=y)        {            for (int j=w;j;j--)                for (int k=1;k<=j;k++)                    g[j]=max(g[j],min(g[j-k],dp(e[i].to,x,z+w-k,k)+e[i].val));        }    return DP[x][y][z][w]=g[w];}void dfs(int x){    for (int i=first[x];i;i=e[i].next)        if (e[i].to!=fa[x])        {            fa[e[i].to]=x,dfs(e[i].to);            tg[x]+=tg[e[i].to];        }}int main(){    n=read();    for (int i=1;i<n;i++)    {        int x=read(),y=read(),z=read();        e[++number].add(x,y,z);        e[++number].add(y,x,z);        d[x]++,d[y]++;        f[x][y]=f[y][x]=z;    }    st=read(),m=read();    for (int i=1;i<=m;i++) tg[read()]++;    dfs(1);    for (int i=first[st];i;i=e[i].next)        if (e[i].to==fa[st]) Ans=min(Ans,dp(e[i].to,st,tg[st],m-tg[st])+e[i].val);        else Ans=min(Ans,dp(e[i].to,st,m-tg[e[i].to],tg[e[i].to])+e[i].val);    printf("%d\n",Ans);    return 0;}

Yet Another Minimization Problem

首先dp[i][j]表示前j个数分成i段的最小代价。
显然具有决策单调性。
k层dp,考虑solve(l,r,L,R)表示这一层的dp[now][l]dp[now][r]的决策点在上一层的dp[last][L]dp[last][R]之间,如果按一般方式寻找mid=l+r2的决策点,递归,某一段数的代价比较难算,考虑类似bfs按层solve下去,每一层类似莫队的方法移动两端点,显然每层最多移动O(n)次,所以总时间复杂度O(knlogn)

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 100009#define inf (ll)0x3f3f3f3f3f3f3f3fusing namespace std;ll n,k,a[N],dp[2][N],num[N],Ans,l=0,r=0;struct node{    ll l,r,x,y;    node(ll l=0,ll r=0,ll x=0,ll y=0):l(l),r(r),x(x),y(y){}}q[N];ll read(){    ll x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    ll s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}void add(ll x){    Ans+=(num[x]++);}void del(ll x){    Ans-=(--num[x]);}ll get(ll x,ll y){    while (r<y) add(a[++r]);    while (l>x) add(a[--l]);    while (r>y) del(a[r--]);    while (l<x) del(a[l++]);    return Ans+dp[0][x-1];}void solve(){    ll L=1,R=1;    q[1]=node(1,n,1,n);    while (L<=R)    {        node now=q[L++];        ll mid=(now.l+now.r)>>1,m=now.x;        for (ll i=now.x;i<=now.y&&i<=mid;i++)        {            ll tmp=get(i,mid);            if (tmp<dp[1][mid]) dp[1][mid]=tmp,m=i;        }        if (now.l<mid) q[++R]=node(now.l,mid-1,now.x,m);        if (mid<now.r) q[++R]=node(mid+1,now.r,m,now.y);    }}int main(){    n=read(),k=read();    for (ll i=1;i<=n;i++) a[i]=read();    memset(dp,inf,sizeof(dp));    dp[1][0]=0;    for (ll t=1;t<=k;t++)    {        for (ll i=0;i<=n;i++) dp[0][i]=dp[1][i];        memset(num,0,sizeof(num)),Ans=r=0,l=1;        solve();    }    printf("%lld\n",dp[1][n]);    return 0;}

(G题似乎策略可以想到,然而完全不会写啊。有空再补吧)

阅读全文
0 0