zoukankan      html  css  js  c++  java
  • 9.2模拟题解

    这次没传送门了……题目懒得copy上来。

    T1.高维宇宙

    这题很明显是二分图匹配,题目中明确说了要配对。

    我一开始的建图方法是有问题的,因为违背了二分图的一个性质,就是在同一个点集中的点是互相不能连边的。那么如何解决这个问题呢?我们知道任何一个大于2的质数必然是奇数,所以我们可以把所有的奇数作为一个点集,所有的偶数作为一个点集,若两者之和为质数则连边,之后跑网络流即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    const int M = 10005;
    const int INF = 1e9;
    typedef long long ll;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct node
    {
        int from,to,next,v;
    }e[M];
    int n,a[105],ecnt = -1,maxflow,deep[105],head[105],prime[20005],tot,source,sink,cur[105];
    int ji[105],ou[105],cnt1,cnt2;
    bool np[20005];
    queue <int> q;
    
    void add(int x,int y,int z)
    {
        e[++ecnt].to = y;
        e[ecnt].v = z;
        e[ecnt].from = x;
        e[ecnt].next = head[x];
        head[x] = ecnt;
    }
    
    void euler()
    {
        np[1] = 1;
        rep(i,2,20000)
        {
            if(!np[i]) prime[++tot] = i;
            for(int j = 1;i * prime[j] <= 20000;j++)
            {
                np[prime[j]*i] = 1;
                if(!(i % prime[j])) break;
            }
        }
    //    rep(i,1,30) printf("%d ",prime[i]);
    }
    
    bool bfs(int s,int t)
    {
        memset(deep,-1,sizeof(deep));
        rep(i,0,sink+1) cur[i] = head[i];
        while(!q.empty()) q.pop();
        deep[s] = 0,q.push(s);
        while(!q.empty())
        {
            int k = q.front();q.pop();
            for(int i = head[k];i != -1;i = e[i].next)
            {
                if(deep[e[i].to] == -1 && e[i].v)
                deep[e[i].to] = deep[k] + 1,q.push(e[i].to);
            }
        }
        if(deep[t] == -1) return 0;
        else return 1;
    }
    
    int dfs(int s,int t,int limit)
    {
        if(s == t || !limit) return limit;
        int flow = 0;
        for(int i = cur[s];i != -1;i = e[i].next)
        {
            cur[s] = i;
            if(deep[e[i].to] != deep[s] + 1) continue;
            int f = dfs(e[i].to,t,min(limit,e[i].v));
            if(f)
            {
                e[i].v -= f,e[i^1].v += f;
                flow += f,limit -= f;
                if(!limit) break;
            }
        }
        if(!flow) deep[s] = -2333333;
        return flow;
    }
    
    void dinic(int s,int t)
    {
        while(bfs(s,t)) maxflow += dfs(s,t,INF);
    }
    
    int main()
    {
    //    freopen("prime.in","r",stdin);
    //    freopen("prime.out","w",stdout);
        memset(head,-1,sizeof(head));
        n = read(),source = 0,sink = 101;
        rep(i,1,n) 
        {
            a[i] = read();
            if(a[i] & 1) ji[++cnt1] = a[i],add(source,cnt1,1),add(cnt1,source,0);
            else ou[++cnt2] = a[i],add(cnt2+n,sink,1),add(sink,cnt2+n,0);
        }
        euler();
        rep(i,1,cnt1)
            rep(j,1,cnt2)
                if(!np[ji[i] + ou[j]]) add(i,j+n,1),add(j+n,i,0);
        dinic(source,sink);
        printf("%d
    ",maxflow);
        return 0;
    }

    T2.旅行

    这题当时没想出来……只写了30pts宽搜暴力。

    这道题的题目描述不是很清晰……既然pppfish要带领一群泡泡怪行走,所以肯定只走一条路径。而且题目都说了可能有多组解……显然不会走很多路径。

    既然如此,我们知道所选择的答案区间肯定是连续的,而且左右端点必然是在边中出现过。所以我们可以选择枚举左端点,之后把所有的边按右端点从大到小排序,之后依次加入,注意加入的边必须合法,也就是当前枚举的左端点必然在这条边的l,r之内才能被加入。每加入一次用并查集判断图是否联通,如联通更新即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    const int M = 10005;
    const int INF = 1e9;
    typedef long long ll;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct edge
    {
        int from,to,next,dl,dr;
        bool operator < (const edge &g) const
        {
            return dr > g.dr;
        }
    }e[M];
    
    int n,m,a,b,l,r,ecnt,head[M],maxn,pos = INF,fa[M],kl,ans,kr;
    bool vis[M];
    
    void add(int x,int y,int l,int r)
    {
        e[++ecnt].to = y;
        e[ecnt].dl = l;
        e[ecnt].dr = r;
        e[ecnt].from = x;
        e[ecnt].next = head[x];
        head[x] = ecnt;
    }
    
    int getfa(int x)
    {
        if(fa[x] == x) return fa[x];
        else return fa[x] = getfa(fa[x]);
    }
    
    bool check()
    {
        int r1 = getfa(1),r2 = getfa(n);
        if(r1 == r2) return 1;
        else return 0;
    }
    
    int main()
    {
        n = read(),m = read();
        rep(i,1,m) a = read(),b = read(),l = read(),r = read(),add(a,b,l,r);
        sort(e+1,e+1+m);
        rep(i,1,m)
        {
            kl = e[i].dl,kr = e[i].dr;
            rep(j,1,n) fa[j] = j;    
            int r1 = getfa(e[i].from),r2 = getfa(e[i].to);
            if(r1 != r2) fa[r1] = r2;
            rep(j,1,m)
            {
                if(kl < e[j].dl || kl > e[j].dr) continue;
                int r1 = getfa(e[j].from),r2 = getfa(e[j].to);
                if(r1 != r2) fa[r1] = r2;
                if(check())
                {
                    kr = min(kr,e[j].dr);
                    int d = kr - kl + 1;
                    if(d > maxn) maxn = d,pos = kl;
                    else if(d == maxn) pos = min(pos,kl);
                    break;
                }
            }
        }
        printf("%d
    ",maxn);
        rep(i,pos,pos+maxn-1) printf("%d ",i);enter;
        return 0;
    }

    T3.字典

    这题本来是会写的……然而考试的时候没时间写跪了,惨淡爆零。

    其实正解很好想,我们要求一个字符串是哪几个字符串的前缀,很容易就想到先建一棵trie树,之后的问题在于,我们怎么维护每个字符串的所得到的答案中的最长全0串。其实我们发现一个0串的长度相当于这个字符串所出现过的相邻两个字符串的编号之差。所以我们可以在建树的时候动态维护差值最大值,之后再访问的时候更新即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    const int M = 505;
    typedef long long ll;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    int cnt = 1,n,m;
    char s[5000005];
    struct trie
    {
        int fir,la,p,v;
    }c[5000005][3];
    
    void insert(int num)
    { 
        int len = strlen(s),now = 1;
        rep(i,0,len-1)
        {
            int k = s[i] - 'a';
            if(!c[now][k].v) c[now][k].v = ++cnt;
            c[now][k].p = max(c[now][k].p,num-c[now][k].la-1);
            c[now][k].la = num;
            now = c[now][k].v;
        }
    }
    
    int query()
    {
        bool flag = 0;
        int len = strlen(s),now = 1,ans;
        rep(i,0,len-1)
        {
            int k = s[i] - 'a';
            if(!c[now][k].v) return n;
            if(i == len-1) return max(c[now][k].p,n - c[now][k].la);
            now = c[now][k].v;
        }
    }
    
    int main()
    {
        n = read(),m = read();
        rep(i,1,n) scanf("%s",s),insert(i);
        rep(i,1,m) scanf("%s",s),printf("%d
    ",query());
        return 0;
    }
  • 相关阅读:
    Python基础 面向对象的基本概念
    C#版菜谱
    Ember源码学习
    AutoFac文档
    NewLife.Xcode组件资源目录
    Go语言
    调试Razor从哪里开始
    搭建一个高并发低时延系统
    ASP.NET MVC以ModelValidator为核心的Model验证体系: ModelValidatorProvider
    2012百度之星资格赛试题与AC代码合集
  • 原文地址:https://www.cnblogs.com/captain1/p/9576354.html
Copyright © 2011-2022 走看看