zoukankan      html  css  js  c++  java
  • 10.7 考试

    T1

    对于每一个G,最小耗时是她前面B的个数,但是当G连在一起时,就有可能把她卡住

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    using namespace std;
    const int N=1000006;
    
    char s[N];
    int n;
    
    int main(){
    
        scanf("%s",s);
        n=strlen(s);
        int ans=0,con=0;
        for(int i=0;i<n;++i)
        {
            if(s[i]=='B')
                ++con;
            else
                ans=max(ans+1,con);
        }
        cout<<ans;
    }
    T1

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    using namespace std;
    const int N=1000006;
    
    char s[N];
    int n;
    int pre[N],nxt[N];
    //bool flag[N];
    
    int work()
    {
        int now=1;
        while(now<=n&&s[now]!='G')++now;
        if(s[now]=='B')
        {
            nxt[0]=n+1;
            pre[n+1]=0;
        }
        else
        {
            nxt[0]=now;
            pre[now]=0;
            for(int i=now;i<=n;)
            {
                now=i;
                while(now<=n&&s[now]=='G')++now;
                while(now<=n&&s[now]=='B')++now;
                pre[now]=i;
                nxt[i]=now;
                i=now;
            }
        }
    
        /*for(int i=nxt[0];i<=n;i=nxt[i])
            printf("i=%d
    ",i);*/
    
        //for(int i=0;i<=n+1;++i)
        //    printf("i=%d %d %d
    ",i,pre[i],nxt[i]);
    
        int t=0,swif;
        while(1)
        {
            ++t;
            swif=0;
            for(int i=nxt[0];i<=n;i=nxt[i])
            {
                //printf("i=%d
    ",i);
                //system("pause");
                if(i==1)
                    continue;
                swif=1;
    
                nxt[pre[i]]=i-1;
                pre[nxt[i]]=i-1;
                pre[i-1]=pre[i];
                nxt[i-1]=nxt[i];
                s[i]='B';
                s[i-1]='G';
                
                if(i-2<1||s[i-2]=='B')
                {
                    if(i+1<=n&&s[i+1]=='G')
                    {
                        pre[nxt[i]]=i+1;
                        nxt[i-1]=i+1;
                        pre[i+1]=i-1;
                        nxt[i+1]=nxt[i];
                    }
                }
                else
                {
                    pre[nxt[i]]=pre[i];
                    nxt[pre[i]]=nxt[i];
                    if(i+1<=n&&s[i+1]=='G')
                    {
                        pre[nxt[i]]=i+1;
                        nxt[pre[i]]=i+1;
                        pre[i+1]=pre[i];
                        nxt[i+1]=nxt[i];
                    }
                }
            }
    
            if(!swif)
                return t-1;
    
            //for(int i=0;i<=n+1;++i)
            //    printf("i=%d %d %d
    ",i,pre[i],nxt[i]);
    
            /*for(int i=1;i<=n;++i)
                printf("%c",s[i]);
            printf("
    ");*/
    
        }
    }
    
    int main(){
    
        //freopen("T1.in","r",stdin);
        //freopen("T111.out","w",stdout);
    
        //freopen("line.in","r",stdin);
        //freopen("line.out","w",stdout);
    
        scanf("%s",s);
        n=strlen(s);
        for(int i=n;i>=1;--i)
            s[i]=s[i-1];
        s[0]=0;
        cout<<work();
        //printf("
    %d
    ",clock());
    }
            /*nxt[0]=now;
            pre[now]=0;
            for(int i=now;i<=n;)
            {
                now=i;
                while(s[now]=='G'&&now<=n)++now;--now;
                if(s[now]=='B')
                {
                    nxt[i]=n+1;
                    pre[n+1]=i;
                }
                else
                    if(now!=i)
                    {
                        pre[now]=i;
                        nxt[i]=now;
                    }
                i=now;
                ++now;
                while(now<=n&&s[now]=='B')++now;
                pre[now]=i;
                nxt[i]=now;
                i=now;
            }*/
    "超快的"链表模拟

     

    T2

    60分dp:

    f[i][j][k] 前i位,最长长度==j,最后一个字符是k

    $$f[i][j][k]=sum_{l=i-j}^{i-1}sum_{p!=k}^mdp[l][j][p]*sum[l+1][j][k]+sum_{h=1}^{j-1}sum_{p!=k}dp[i-j][h][p]*sum[i-j+1][i][k]$$

    其中sum是从i到j字符全是k的概率,$O(n^2m)$求出

    正解有两个,一个是$O(n^2m^2)$的,一个是$O(n^2m)$的

    后一个更好理解,也更快

    dp[i][j][k] 到了第i个位置,最长长度<=j,最后一个字符是k 的概率

    f[i][j] 到了第i个位置,最长长度<=j 的概率 (其实就是把dp的第三维去掉了)

    $$dp[i][j][k]=f[i-1][j]*sum[i][i][k]-(f[i-j-1][j]-dp[i-j-1][j][k])*sum[i-j][i][k]$$

    其实就是把所有情况都先转移过来,然后去掉不合法的情况

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #define dd double
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    int n,m;
    dd p[1006][16];
    dd s[1006][1006][16];
    dd f[1006][1006],dp[1006][1006][16];
    
    void chu()
    {
        for(int i=1;i<=m;++i)
            p[0][i]=1.0;
    
        for(int k=1;k<=m;++k)
            for(int i=1;i<=n;++i)
            {
                s[i][i][k]=p[i][k];
                for(int j=i+1;j<=n;++j)
                    s[i][j][k]=s[i][j-1][k]*p[j][k];
            }
    }
    
    dd work()
    {
        dd ans=0;
        for(int i=0;i<=n;++i)
            f[0][i]=1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                for(int k=1;k<=m;++k)
                {
                    //printf("i=%d j=%d k=%d
    ",i,j,k);
                    dp[i][j][k]=f[i-1][j]*s[i][i][k];
                    if(i-j-1>=0)
                        dp[i][j][k]-=(f[i-j-1][j]-dp[i-j-1][j][k])*s[i-j][i][k];
                    f[i][j]+=dp[i][j][k];
                }
        for(int j=1;j<=n;++j)
            ans+=(f[n][j]-f[n][j-1])*j;
        return ans;
    }
    
    int main(){
    
        //freopen("1.in","r",stdin);
    
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                scanf("%lf",&p[i][j]);
        chu();
        printf("%.5lf",work());
    }
    T2

     

    T3

    设B=sqrt(n)

    把集合大小>B的定为重集合,<=B的定为轻集合

    处理一个数组cnt[][]记录每一个集合与重集合的交集个数,这个可以$O(nsqrt{n})$处理

    每一个重集合维护 sum、add,分别表示重集合不加标记的值和标记的值

    然后插入、询问分4个操作:

    1.轻集合add,暴力加轻集合内的元素,再更新与之有交集的重集合的sum

    2.重集合add,直接标记

    3.轻集合qq,直接暴力统计+与之有交集的重集合标记*cnt[i][j]

    4.重集合qq,sum+与之有交集的重集合标记*cnt[i][j]

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    using namespace std;
    const int N=100006;
    
    int n,m,Q;
    int B;
    ll a[N];
    
    vector<int> ji[N],dian[N];
    int num[N];
    
    int zhong[N],con,dui[N];
    int cnt[N][336];
    
    ll biao[N],sum[N];
    
    void chu()
    {
        int temp,s1,s2;
        for(int i=1;i<=m;++i)
        {
            for(int j=0;j<num[i];++j)
            {
                s1=dian[ji[i][j]].size();
                for(int k=0;k<s1;++k)
                    ++cnt[i][ dian[ji[i][j]][k] ];
            }
        }
    }
    
    ll qq(int x)
    {
        ll ans=0;
        if(num[x]>B)
        {
            ans+=sum[dui[x]];
            for(int i=1;i<=con;++i)
                ans+=cnt[x][i]*biao[i];
            return ans;
        }
        for(int i=0;i<num[x];++i)
            ans+=a[ji[x][i]];
        for(int i=1;i<=con;++i)
            ans+=cnt[x][i]*biao[i];
        return ans;
    }
    
    void add(int x,int val)
    {
        if(num[x]>B)
        {
            biao[dui[x]]+=val;
            return ;
        }
        for(int i=0;i<num[x];++i)
            a[ji[x][i]]+=val;
        for(int i=1;i<=con;++i)
            sum[i]+=cnt[x][i]*val;
    }
    
    int main(){
    
        scanf("%d%d%d",&n,&m,&Q);
        B=sqrt(n);
        for(int i=1;i<=n;++i)
            scanf("%lld",&a[i]);
        int tin1,tin2;
        for(int i=1;i<=m;++i)
        {
            scanf("%d",&num[i]);
            if(num[i]>B)
            {
                zhong[++con]=i;
                dui[i]=con;
            }
            for(int j=1;j<=num[i];++j)
            {
                scanf("%d",&tin1);
                ji[i].push_back(tin1);
                if(zhong[con]==i)
                {
                    dian[tin1].push_back(con);
                    sum[con]+=a[tin1];
                }
            }
        }
        chu();
        int op;
        for(int i=1;i<=Q;++i)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d",&tin1);
                printf("%lld
    ",qq(tin1));
            }
            else
            {
                scanf("%d%d",&tin1,&tin2);
                add(tin1,tin2);
            }
        }
    }
    T3

     

     

    总结:

    第一题是思考题,但是我一意孤行的认为跟 clock 那个题一样 打了链表...

    对于2.3题,当然要打暴力了....

    但是最近总是想不出来...

     

  • 相关阅读:
    Docker
    dcoker-componse-2
    MyBatis的基本使用
    SpringMVC实现文件上传和下载
    CF817E Choosing The Commander
    CSP 2020 游记
    COCI2014-2015 Contest#1 题目选做
    CF590D Top Secret Task
    LuoguP1937 [USACO10MAR]Barn Allocation G
    CF741C Arpa’s overnight party and Mehrdad’s silent entering
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7636486.html
Copyright © 2011-2022 走看看