zoukankan      html  css  js  c++  java
  • 《PTA练习*补》

    列车调度 (25分):

    这题被之前做过的一个列车的题误导了,一直以为是栈的运用,就一直在思考栈的方向,最后挂了..

    思路:

    因为是递减出去,所以肯定是大的列车先出去,所以,对于每个车,要开辟新的位置来存放它,就是后面有比他大的。

    因为如果比他大的插入在某个位置后面,那个大的值显然不是队首,不能先出去。

    那么,这题就是个nlogn求最长上升子序列的问题。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 5e5+5;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL 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;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    int dp[N],a[N];
    int main()
    {
        int n;n = read();
        for(int i = 1;i <= n;++i) a[i] = read();
        int len = 0;
        dp[++len] = a[1];
        for(int i = 2;i <= n;++i)
        {
            if(dp[len] < a[i]) dp[++len] = a[i];
            else 
            {
                int pos = upper_bound(dp+1,dp+len+1,a[i])-dp;
                dp[pos] = a[i];
            }
        }
        printf("%d
    ",len);
        system("pause");    
    }
    View Code

    二叉搜索树的结构 (30分)

    这题一开始二叉树的写法觉得指针很麻烦,就用了动态开点的线段树来写了。

    插入之后计算下fa,dep数组就很简单了。

    这里有两个坑点没注意少了6分。

    1:节点数据可能很大,要离散化(其实这里想到了,只是没时间去写了。)

    2:因为节点数据随机,不存在用0会被卡,要用更特殊的(这里用了-13)。然后可能查询的节点可能不存在,这里也要特判

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e6+5;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e8
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL 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;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    struct Node{
        int val,L,r;
    }node[N*20];
    map<int,int> mp;
    int rt = -13,fa[105],dep[105],L[105],R[105],cnt = 0,tim = 0;
    void Insert(int &idx,int x)
    {
        if(idx == -13)
        {
            idx = ++cnt;
            if(rt == -13) rt = cnt;
            node[idx].val = x;
            node[idx].L = node[idx].r = -13;
            return ;
        }
        if(x < node[idx].val) Insert(node[idx].L,x);
        else Insert(node[idx].r,x);
    }
    void dfs(int idx,int ffa,int tag)
    {
        if(idx == -13) return ;
        int u = node[idx].val;
        if(ffa != -13)
        {
            dep[mp[u]] = dep[mp[ffa]]+1;
            fa[mp[u]] = ffa;//存具体的值
            if(tag == 0) L[mp[ffa]] = u;
            else R[mp[ffa]] = u;
        }
        dfs(node[idx].L,u,0);
        dfs(node[idx].r,u,1);
    }
    int main()
    {
        int n;n = read();
        while(n--)
        {
            int x;x = read();
            mp[x] = ++tim;
            Insert(rt,x);
        }
        dfs(rt,-13,0);
        int m;m = read();
        while(m--)
        {
            int x,y;x = read();
            string s;cin >> s;
            if(s == "is")
            {
                string the,a,b;cin >> the >> a;
                if(a == "root") printf("%s
    ",node[rt].val == x && mp[x] != 0 ? "Yes" : "No");
                else if(a == "parent")
                {
                    cin >> b >> y;
                    printf("%s
    ",fa[mp[y]] == x && mp[y] != 0 && mp[x] != 0 ? "Yes" : "No");
                }
                else if(a == "left")
                {
                    string c,d;cin >> c >> d >> y;
                    printf("%s
    ",L[mp[y]] == x && mp[y] != 0 && mp[x] != 0 ? "Yes" : "No");
                }
                else
                {
                    string c,d;cin >> c >> d >> y;
                    printf("%s
    ",R[mp[y]] == x && mp[x] != 0 && mp[y] != 0 ? "Yes" : "No");
                }
            }
            else
            {
                cin >> y;
                string a,b;cin >> a >> b;
                if(b == "siblings") printf("%s
    ",fa[mp[x]] == fa[mp[y]] && mp[x] != 0 && mp[y] != 0 ? "Yes" : "No");
                else
                {
                    string c,d,e;cin >> c >> d >> e;
                    printf("%s
    ",dep[mp[x]] == dep[mp[y]] && mp[x] != 0 && mp[y] != 0 ? "Yes" : "No");
                }
            }
        }
        system("pause");
    }
    View Code

     L3-001 凑零钱 (30分)

    01背包路径打印。

    解法1:dfs暴搜。

    剪枝够强就能过。

    这里可以的话,如果后面的数很大,那么很容易就超m,剪枝掉。

    然后很小的数的话,就可能有很层了,那么这里就需要一个很重要的剪枝,记录一下后缀和,当剩下的全部都无法凑成,就return。

    解法2:dp。

    看到网上都是把价值当作容量来dp的。

    其实根本不需要,因为这题要打印的是最小序列,所以我们可以对数组降序,后面如果到了i,i可以和前面的凑成m,显然i这组字典序更小。

    因为我们降序排后,i肯定比前面的都小,那么加入i,显然可以使字典序最小。

    然后记录下就行,最后我们从后往前判断输出

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e4+5;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e8
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL 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;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    int a[N];
    int dp[105],pre[N][105];
    int main()
    {
        int n,m;n = read(),m = read();
        for(int i = 1;i <= n;++i) a[i] = read();
        sort(a+1,a+n+1,greater<int>());
        dp[0] = 1;
        for(int i = 1;i <= n;++i)
        {
            for(int j = m;j >= a[i];--j)
            {
                if(dp[j-a[i]] == 0) continue;
                dp[j] = 1;
                pre[i][j] = 1;
            }
        }
        if(!dp[m]) printf("No Solution
    ");
        else
        {
            int f = 1;
            for(int i = n;i >= 1;--i)
            {
                if(pre[i][m])
                {
                    if(f) printf("%d",a[i]);
                    else printf(" %d",a[i]);
                    m -= a[i];
                    f = 0;
                }
            }
        }
        system("pause");
    }
    View Code

     L1-006 连续因子 (20分)

    这题一开始题意没读懂..

    其实就是求某段连续因子,并且这段因子不需要满足相乘 = n,只要能整除就行。

    那么,显然筛到sqrt(n)就够,因为sqrt(n) * sqrt(n)+1肯定 > n,然后枚举连续的开头,再去找就行。

    这里有一个坑点,就是一个因子也比他自己本身因子要小。

    所以满足自己是因子的只有素数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 360;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL 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;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    
    int main()
    {
        int n;n = read();
        int len = 0,st = 0,m = sqrt(n);
        for(rg int i = 2;i <= m;++i)
        {
            if(n % i == 0)
            {
                int ma = n,j = i,tmp = 0;
                while(ma % j == 0)
                {
                    tmp++;
                    ma /= j;
                    j++;
                }
                if(tmp > len)
                {
                    len = tmp,st = i;
                }
            }
        }    
        if(len == 0) printf("1
    %d
    ",n);
        else
        {
            printf("%d
    ",len);
            for(int i = st;i <= st+len-1;++i) printf("%d%c",i,i == st+len-1 ? '
    ' : '*');
        }
        system("pause");
    }
    View Code

     7-14 二叉搜索树的最近公共祖先 (30分)

    终于a了。

    一开始TLE应该是因为insert中map调用太多次了。

    实际上这里是可以离散化数据的(一开始以为不能离散化)

    离散化之后要注意根的点和值。然后常数优化倍增就行了。

    复杂度肯定是够的,就是细节调了很久。。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e4+5;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL 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;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    int m,n,tot = 0,cnt = 0,rt = 0;
    int fa[N],L[N],r[N],val[N],dep[N],f[N][25],lg[N],a[N],b[N];
    vector<int> G[N];
    inline void init()
    {
        for(rg int i = 1;i < N;++i) lg[i] = lg[i-1] + ((1<<lg[i-1]) == i);
    }
    void Insert(int now,int ffa,int x,int id)
    {
        if(now == 0)
        {
            if(id == 1) L[ffa] = x;
            else r[ffa] = x;
            fa[x] = ffa;
        }
        else
        {
            if(val[x] > val[now]) Insert(r[now],now,x,0);
            else Insert(L[now],now,x,1);
        }
    }
    void dfs(int u,int fa)
    {
        dep[u] = dep[fa]+1;f[u][0] = fa;
        for(rg int i = 1;i <= lg[dep[u]];++i) f[u][i] = f[f[u][i-1]][i-1];
        for(auto v : G[u]) if(v != fa) dfs(v,u);
    }
    int LCA(int x,int y)
    {
        if(dep[x] < dep[y]) swap(x,y);
        while(dep[x] > dep[y]) x = f[x][lg[dep[x]-dep[y]]-1];
        if(x == y) return x;
        for(rg int i = lg[dep[x]]-1;i >= 0;--i) if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i];
        return f[x][0];
    }
    int main()
    {
        init();
        m = read(),n = read();
        for(rg int i = 1;i <= n;++i) a[i] = read(),b[i] = a[i];
        sort(a+1,a+n+1);
        for(rg int i = 1;i <= n;++i)
        {
            int ma = b[i];
            b[i] = lower_bound(a+1,a+n+1,b[i])-a;
            val[b[i]] = ma;
            L[b[i]] = r[b[i]] = 0;
            if(rt == 0) rt = b[i];
            else Insert(rt,0,b[i],0);
        }
        for(rg int i = 1;i <= n;++i) if(fa[i] != 0) G[i].push_back(fa[i]),G[fa[i]].push_back(i);
        dfs(rt,0);
        while(m--)
        {
            int u,v;u = read(),v = read();
            int pos1 = lower_bound(a+1,a+n+1,u)-a;
            int pos2 = lower_bound(a+1,a+n+1,v)-a;
            int f1 = 0,f2 = 0;
            if(pos1 > n || a[pos1] != u) f1 = 1;
            if(pos2 > n || a[pos2] != v) f2 = 1;
            if(f1 && f2) printf("ERROR: %d and %d are not found.
    ",u,v);
            else if(f1) printf("ERROR: %d is not found.
    ",u);
            else if(f2) printf("ERROR: %d is not found.
    ",v);
            else 
            {
                int lca = LCA(pos1,pos2);
                if(val[lca] == u) printf("%d is an ancestor of %d.
    ",u,v);
                else if(val[lca] == v) printf("%d is an ancestor of %d.
    ",v,u);
                else printf("LCA of %d and %d is %d.
    ",u,v,val[lca]);
            }
        }
        system("pause");
    }
    View Code

     7-84 关键活动 (30分)

    这个题关于了一个AOE网中的概念。

    补了补。

    对于关键路径就是无环的有向带权图中的最长完工路径。

    同时这条路径也是保证工程完成的最短时间。

    而关键活动就是这条路径上的路径。

    对于关键路径的求解:需要两次拓扑排序,去更新最早开始时间,和最早完工时间。

    首先判环。没环才存在。

    对于最早开始时间,因为需要前面的依赖工作都完成,才去干下面的,所以是去max值。

    对于最早完工时间,从建反图,从终点开始拓扑,取min去位置。

    最后对于一条路径,如果它的权值 = 它的结束节点的最早完工时间 - 它的开始节点的最早开始时间,那么就是关键活动。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5+5;
    const int M = 1e6+5;
    const LL Mod = 1e9+7;
    #define pi acos(-1)
    #define INF 1e18
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL 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;
        }
    }
    using namespace FASTIO;
    
    int in[105],on[105],n,m,st[105],ed[105];
    vector<pii> G[105],RG[105];
    struct Node{int x,y;};
    bool cmp(Node a,Node b)
    {
        if(a.x == b.x) return a.y > b.y;
        else return a.x < b.x;
    }
    int tim;
    bool solve()
    {
        memset(st,0,sizeof(st));
        memset(ed,0x3f,sizeof(ed));
        queue<int> Q;
        for(int i = 1;i <= n;++i) if(in[i] == 0) Q.push(i);
        int ans = 0;
        while(!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            ans++;
            for(auto v : G[u])
            {
                st[v.first] = max(st[v.first],st[u] + v.second);
                in[v.first]--;
                if(in[v.first] == 0) Q.push(v.first);
            }
        }
        if(ans < n) return false;
        int mxtim = 0,pos = 0;
        for(int i = 1;i <= n;++i) if(st[i] > mxtim) mxtim = st[i],pos = i;
        ed[pos] = mxtim;
        while(!Q.empty()) Q.pop();
        for(int i = 1;i <= n;++i) if(on[i] == 0) Q.push(i);
        while(!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            for(auto v : RG[u])
            {
                ed[v.first] = min(ed[v.first],ed[u] - v.second);
                on[v.first]--;
                if(on[v.first] == 0) Q.push(v.first);
            }
        }
        tim = mxtim;
        return true;
    }
    int main()
    {
        n = read(),m = read();
        while(m--)
        {
            int x,y,tim;x = read(),y = read(),tim = read();
            G[x].push_back(pii{y,tim});
            RG[y].push_back(pii{x,tim});
            in[y]++,on[x]++;
        }
        if(!solve()) printf("0
    ");
        else
        {
            //for(int i = 1;i <= n;++i) printf("st[%d] is %d ed[%d] is %d
    ",i,st[i],i,ed[i]);
            printf("%d
    ",tim);
            vector<Node> ans;
            for(int i = 1;i <= n;++i)
            {
                for(auto v : G[i])
                {
                    if(ed[v.first] - st[i] == v.second) ans.push_back(Node{i,v.first});
                }
            }
            sort(ans.begin(),ans.end(),cmp);
            for(auto v : ans) printf("%d->%d
    ",v.x,v.y);
        }
      //  system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    水晶苍蝇拍:到底怎样把握企业的内在价值? (2010-12-29 15:37:11)
    水晶苍蝇拍:个人投资者必须学会扬长避短 (2010-12-24 12:04:59)
    水晶苍蝇拍:公司研究不要“就事论事”而要“逻辑支点” (2010-12-23 10:58:23)
    水晶苍蝇拍:再高的学识也扛不住“浮躁” (2010-12-03 08:31:33)
    水晶苍蝇拍:人生不同阶段的投资规划 (2010-12-01 08:20:13)
    水晶苍蝇拍:好公司的3个判断维度:成长前景-机会程度-生意属性 (2010-11-29 08:32:30)
    水晶苍蝇拍:我为什么不会重仓买入银行股? (2010-11-28 10:20:00)
    水晶苍蝇拍:投资随谈之:关于股价的“溢价与泡沫” (2010-11-25 08:21:01)
    fgets汉字问题
    sizeof('a')
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13661112.html
Copyright © 2011-2022 走看看