《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\n",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\n",node[rt].val == x && mp[x] != 0 ? "Yes" : "No");
            else if(a == "parent")
            {
                cin >> b >> y;
                printf("%s\n",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\n",L[mp[y]] == x && mp[y] != 0 && mp[x] != 0 ? "Yes" : "No");
            }
            else
            {
                string c,d;cin >> c >> d >> y;
                printf("%s\n",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\n",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\n",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\n");
    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\n%d\n",n);
    else
    {
        printf("%d\n",len);
        for(int i = st;i <= st+len-1;++i) printf("%d%c",i,i == st+len-1 ? '\n' : '*');
    }
    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.\n",u,v);
        else if(f1) printf("ERROR: %d is not found.\n",u);
        else if(f2) printf("ERROR: %d is not found.\n",v);
        else 
        {
            int lca = LCA(pos1,pos2);
            if(val[lca] == u) printf("%d is an ancestor of %d.\n",u,v);
            else if(val[lca] == v) printf("%d is an ancestor of %d.\n",v,u);
            else printf("LCA of %d and %d is %d.\n",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\n");
    else
    {
        //for(int i = 1;i <= n;++i) printf("st[%d] is %d ed[%d] is %d\n",i,st[i],i,ed[i]);
        printf("%d\n",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\n",v.x,v.y);
    }
  //  system("pause");
    return 0;
}
View Code

 

posted @ 2020-09-13 13:27  levill  阅读(178)  评论(0编辑  收藏  举报