zoukankan      html  css  js  c++  java
  • 暑假爆零欢乐赛SRM08题解

      这真的是披着CF外衣的OI赛制?我怎么觉得这是披着部分分外衣的CF?果然每逢cf赛制必掉rating,还是得%%%cyc橙名爷++rp。。

      A题就是找一找序列里有没有两个连在一起的0或1,并且不能向两端延伸(比如……1001……或110……或者……100),找到了之后就可以把整个序列分成这两个数左边,这两个数和他的右边三部分,然后这两个0或1每个都能与左边右边串在一起构成两个相同的子序列,并且这个子序列在原序列中只会出现这两次,满足题目条件。如果没找到,再看看原来的序列里是不是只有两个0或1,那么这样单独一个0或1也只在序列里出现两次。要是上边两种情况都不满足,那么随便想想知道不可能存在只出现两次的子序列。(cyc写n>10输出Y也过了,,,n很大的时候N的概率确实很小)

    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    char s[5010];
    int main()
    {
        int n,i,sum=0;
        scanf("%s",s); n=strlen(s);
        for(i=0;i<n;i++)
            if(s[i]=='0')sum++;
        int flag=0;
        if(sum==2||n-sum==2||(s[0]==s[1]&&s[1]!=s[2]))flag=1;
        for(i=3;i<=n;i++)
            if(s[i-3]!=s[i-2]&&s[i-2]==s[i-1]&&s[i-1]!=s[i])flag=1;
        if(flag)printf("Y");else printf("N");
    }
    A

      B的话可以写bit优化dp(似乎也可以splay优化?不过我不会。。。)。用f[i][j]表示b序列跑到第i个数,a序列跑到第j个数的方案数,于是方程就是f[i][j]=sum(f[i-1][k])(1<=k<j&&b[i]+a[j]>=b[i-1]+a[k]),然后这个式子可以转化成a[k]<=b[i]-b[i-1]+a[j],把a排个序之后发现这个k的取值是连续的,就能愉快地bit单点修改+前缀和查询了。

    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    const int mod=1000000007;
    int n,m;
    struct data{
        int x,id;
    }a[2010];
    int b[1010],rank[2010],c[2010],f[1010][2010];
    bool cmp(data a,data b){return a.x<b.x;}
    int low(int x){return x&(-x);}
    void add(int x,int k){for(;x<=n;x+=low(x))c[x]=(c[x]+k)%mod;}
    int work(int x){int sum=0;for(;x;x-=low(x))sum=(sum+c[x])%mod;return sum;}
    int main()
    {
        int i,j;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i;
        for(i=1;i<=m;i++)scanf("%d",&b[i]);
        sort(a+1,a+n+1,cmp);
        for(i=1;i<=n;i++)rank[a[i].id]=i;
        for(i=1;i<=n;i++)f[1][i]=1;
        for(i=2;i<=m;i++){
            for(j=1;j<=n;j++)c[j]=0;
            for(j=1;j<=n;j++){
                int l=0,r=n+1;
                while(l+1<r){
                    int mid=(l+r)>>1;
                    if(a[mid].x>b[i]-b[i-1]+a[rank[j]].x)r=mid;else l=mid;
                }
                f[i][j]=work(l); add(rank[j],f[i-1][j]);
            }
        }
        int ans=0;
        for(i=1;i<=n;i++)ans=(ans+f[m][i])%mod;
        printf("%d",ans);
    }
    B

      C的话,,,cyc的和正解的解法没看懂。不过看了tjm的代码,,,纳尼?随机化?把点随机对半分然后跑最短路,然后重复几次取最小值?不过这样如果rp不好没膜大佬还是会挂。。。那么有没有不用随机化的方法呢?我们发现把点集对半分后,没有跑过最短路的点对的两个点都是在这两个点集的某一个中,于是我们把两个点集每个再分成两半,第一个分成AB两部分,第二个分成CD两部分,然后把AC和BD重组成两个点集再跑一次。这样分分分分下去,分log(k)次,每个点对的距离肯定会在某一次跑最短路中被统计进答案。不过这样实现还是有点麻烦,直接把k个特殊点标号,然后按照每一二进制位的值分集合,实现就简便多了。

    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    int fir[100010],to[600010],w[600010],ne[600010];
    int dist[100010],q[5000010],inq[100010];
    int a[10010];
    int n,m,k,tot=0;
    void add(int x,int y,int z){to[++tot]=y; w[tot]=z; ne[tot]=fir[x]; fir[x]=tot;}
    int spfa(int p)
    {
        int i,h=1,t=0;
        for(i=1;i<=n;i++)dist[i]=1<<30,inq[i]=0;
        for(i=1;i<=k;i++)
            if(i&(1<<p))q[++t]=a[i],dist[a[i]]=0,inq[a[i]]=1;
        while(h<=t){
            for(i=fir[q[h]];i;i=ne[i])
                if(dist[q[h]]+w[i]<dist[to[i]]){
                    dist[to[i]]=dist[q[h]]+w[i];
                    if(!inq[to[i]]){
                        q[++t]=to[i]; inq[to[i]]=1;
                    }
                }
            inq[q[h++]]=0; 
        }
        int ans=1<<30;
        for(i=1;i<=k;i++)
            if(!(i&(1<<p)))ans=min(ans,dist[a[i]]);
        return ans;
    }
    int main()
    {
        int i,x,y,z;
        scanf("%d%d%d",&n,&m,&k);
        for(i=1;i<=k;i++)scanf("%d",&a[i]);
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z);
        }
        int ans=1<<30;
        for(i=0;i<=log(k);i++)ans=min(ans,spfa(i));
        printf("%d",ans);
    }
    C
  • 相关阅读:
    CMD文件分析
    #ifdef __cplusplus
    nginx查看post请求日志
    JNI常见错误1
    include、include_once与require、require_once区别
    在Windows下利用Eclipse调试FFmpeg
    在Windows下利用MinGW编译FFmpeg
    图文详解YUV420, yuv格式2
    yuv rgb 像素格式1
    libyuv 编译for ios
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/7246124.html
Copyright © 2011-2022 走看看