zoukankan      html  css  js  c++  java
  • 《牛客练习赛67》

    A:因为数太大,所以按字符串存即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 2e6+5;
    const LL Mod = 998244353;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int 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;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        string s;
        while(getline(cin,s))
        {
            string t = "";
            vector<string> ans;
            int pre = 0;
            for(int i = 0;i < s.size();++i)
            {
                if(s[i] >= '0' && s[i] <= '9')
                {
                    if(s[i] == '0' && t == "") pre++;
                    else t += s[i];
                }
                else
                {
                    if(t != "") ans.push_back(t);
                    else if(t == "" && pre != 0) ans.push_back("0");
                    pre = 0;
                    t = "";
                }
            }
            if(t != "") ans.push_back(t);
            else if(t == "" && pre != 0) ans.push_back("0");
            if(ans.size() == 0) cout << endl;
            else
            {
                for(int i = 0;i < ans.size();++i) 
                {
                    cout << ans[i];
                    if(i == ans.size()-1) cout << endl;
                    else cout << " ";
                }
            }
        }
       // system("pause");
        return 0;
    }
    View Code

    B:显然是最大的那个数

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 2e6+5;
    const LL Mod = 998244353;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int 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;
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            int n;n = read();
            int mx = -1;
            for(int i = 1;i <= n;++i)
            {
                int x;x = read();
                mx = max(mx,x);
            }
            if(mx < 0) mx = 0;
            printf("%d\n",mx);
        }
       // system("pause");
        return 0;
    }
    View Code

    C:手推几个就可以发现3的倍数必败,其他必胜

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 2e6+5;
    const LL Mod = 998244353;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    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;
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            LL n;n = read();   
            if(n%3 == 0) printf("Frame\n");
            else printf("Alan\n");
        }
      //  system("pause");
        return 0;
    }
    View Code

    D:DP转移

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 2e6+5;
    const LL Mod = 998244353;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    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;
    }
    int a[N];
    int dp[N][2],f[N];//dp[i][0]-全变0的最小代价,dp[i][1]-全变1的最小代价
    int main()
    {
        int n;n = read();
        for(int i = 1;i <= n;++i) a[i] = read();
        int sum = 0;
        if(a[1] == 1)
        {
            dp[1][1] = 0;
            dp[1][0] = 1;
        }
        else
        {
            dp[1][0] = 0;
            dp[1][1] = 1;
        }
        for(int i = 2;i <= n;++i)
        {
            if(a[i] == 0)
            {
                dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1);
                dp[i][1] = min(dp[i-1][1]+1,dp[i-1][0]+1);
            }
            else
            {
                dp[i][1] = min(dp[i-1][1],dp[i-1][0]+1);
                dp[i][0] = min(dp[i-1][1]+1,dp[i-1][0]+1);
            }
           // printf("i is %d dp0 is %d dp1 is %d\n",i,dp[i][0],dp[i][1]);
        }
        int ans = min(dp[n][0],dp[n][1]+1);
        printf("%d\n",ans);
        //system("pause");
        return 0;
    }
    View Code

    E:

    注意lowbit的定义是最小的为1的二进制位。

    首先暴力建边n*2,可以不行。

    这里建32个虚拟点,表示二进制位i的站点。

    那么可以发现,如果这个数i位上是1,那么就可以和代表i的虚拟点连边,代价为(1<<i)。

    然后虚拟点到其他点的代价都为0.最后跑一次最短路即可。

    那么,为什么这样建边就能保证最小了,不会比原先的答案还小吗?

    可以发现,如果可以建边,那么说明这个数这个位上有1,如果更低位上有1,那么会满足lowbit的定义。

    显然,会用更低的代价去松弛答案,这样可以保证到最小。至于不会超答案,这很显然,如果能到,说明可以松弛到。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 2e6+5;
    const LL Mod = 998244353;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    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;
    }
    LL a[N],dis[N<<1];
    struct Node{int to;LL dis;};
    vector<Node> G[N<<1];
    /*
    [0,34] - []
    */
    int n,m;
    void slove()
    {
        for(int i = 1;i <= m;++i) dis[i] = INF;
        priority_queue<pii,vector<pii>,greater<pii> > Q;
        dis[1] = 0;
        Q.push(pii{0,1});
        while(!Q.empty())
        {
            int u = Q.top().second;
            LL d = Q.top().first;
            Q.pop();
            if(d > dis[u]) continue;
            for(auto t : G[u])
            {
                if(dis[t.to] > dis[u]+t.dis)
                {
                    dis[t.to] = dis[u]+t.dis;
                    Q.push(pii{dis[t.to],t.to});
                }
            }
        }
    }   
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            n = read();
            for(rg int i = 1;i <= n;++i) a[i] = read();
            m = n+35;
            for(rg int i = 1;i <= m;++i) G[i].clear();
            for(rg int i = 1;i <= n;++i)
            {
                for(rg int j = 0;j < 35;++j)
                {
                    if((a[i]>>j)&1) 
                    {
                        G[i].push_back(Node{n+j+1,1LL<<j});
                        G[n+j+1].push_back(Node{i,0});
                    }
                }
            }
            slove();
            if(dis[n] == INF) printf("Impossible\n");
            else printf("%lld\n",dis[n]); 
        }
        //system("pause");    
        return 0;
    }
    View Code

    F:

    一开始一直在想树剖来着。。(不过树剖也可以做)。

    解法:可以发现,对于区间[L,R]里的最大权值,显然是区间的直径(即区间内最远的两个点)

    那么我们可以用st[i][j]来表示i位置包含i后面开始2^j个位置里的直接的两个数,因为是两个数,可以要用pair来存。

    那么st[i][j]合并,这里可以发现,是类似st表的合并。从st[i][j-1]和st[i+(1<<j)][j-1]来转移。

    这里我们还可以发现的是,对于两个区间的直径的合并,显然新的直径是四个点里(即原先两个区间的直径点)距离最远的两个点。(这也很显然,可以画图理解,就三种链与点的关系)

    那么我们就可以转移最大值。到这里就差不多了。

    但是这题卡时间卡的厉害。vector被卡。然后因为LCA也用了太多次了,必须用ST来求LCA,不然也会T

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<int,int> pii;
    const int N = 3e5+5;
    const int M = 2e6+5;
    const LL Mod = 998244353;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int 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;
    }
    int lg[N<<1],head[N],f[N<<1][20],dfn[N],dep[N];
    LL way[N];
    int n,q,cnt = 0,tot = 0;
    pii st[N][32];
    struct Node{int to,next;LL dis;}e[N<<1];
    inline void add(int u,int v,LL w)
    {
        e[++cnt].to = v,e[cnt].dis = w,e[cnt].next = head[u],head[u] = cnt;
    }
    void dfs(int u,int fa)
    {
        dep[u] = dep[fa]+1;
        f[++tot][0] = u;
        dfn[u] = tot;
        for(rg int i = head[u];i;i = e[i].next)
        {
            if(e[i].to == fa) continue;
            way[e[i].to] = way[u]+e[i].dis;
            dfs(e[i].to,u);
            f[++tot][0] = u;
        }
    }
    void init()
    {
        lg[1] = 0;for(rg int i = 2;i <= tot;++i) lg[i] = lg[i>>1]+1;
        for(rg int j = 1;j <= 19;++j)
        {
            for(rg int i = 1;i+(1<<j)-1 <= tot;++i)
            {
                if(dep[f[i][j-1]] <= dep[f[i+(1<<j-1)][j-1]]) f[i][j] = f[i][j-1];
                else f[i][j] = f[i+(1<<j-1)][j-1];
            }
        }
    }
    int LCA(int x,int y)
    {
        x = dfn[x],y = dfn[y];
        if(x > y) swap(x,y);
        int k = lg[y-x+1];
        if(dep[f[x][k]] < dep[f[y-(1<<k)+1][k]]) return f[x][k];
        return f[y-(1<<k)+1][k];
    }
    LL dis(int x,int y)
    {
        return way[x]+way[y]-2LL*way[LCA(x,y)];
    }
    pii check(pii a,pii b)
    {
        LL ma1 = dis(a.first,b.first);
        LL ma2 = dis(a.first,b.second);
        LL ma3 = dis(a.second,b.first);
        LL ma4 = dis(a.second,b.second);
        LL ma5 = dis(a.first,a.second);
        LL ma6 = dis(b.first,b.second);
        if(ma1 >= ma2 && ma1 >= ma3 && ma1 >= ma4 && ma1 >= ma5 && ma1 >= ma6) return pii{a.first,b.first};
        if(ma2 >= ma1 && ma2 >= ma3 && ma2 >= ma4 && ma2 >= ma5 && ma2 >= ma6) return pii{a.first,b.second};
        if(ma3 >= ma1 && ma3 >= ma2 && ma3 >= ma4 && ma3 >= ma5 && ma3 >= ma6) return pii{a.second,b.first};
        if(ma4 >= ma1 && ma4 >= ma2 && ma4 >= ma3 && ma4 >= ma5 && ma4 >= ma6) return pii{a.second,b.second};
        if(ma5 >= ma1 && ma5 >= ma2 && ma5 >= ma3 && ma5 >= ma4 && ma5 >= ma6) return pii{a.first,a.second};
        return pii{b.first,b.second};
    }
    void pre()
    {
        for(rg int i = 1;i <= n;++i) st[i][0] = pii{i,i};
        for(rg int j = 1;j <= 19;++j)
        {
            for(rg int i = 1;i+(1<<j)-1 <= n;++i)
            {
                st[i][j] = check(st[i][j-1],st[i+(1<<(j-1))][j-1]);
            }
        }
    }
    LL query(int x,int y)
    {
        int k = lg[y-x+1];
        pii ma = check(st[x][k],st[y-(1<<k)+1][k]);
        return dis(ma.first,ma.second);
    }
    int main()
    {
        n = read(),q = read();
        for(rg int i = 1;i < n;++i)
        {
            int u,v,w;u = read(),v = read(),w = read();
            add(u,v,w);add(v,u,w);
        }
        dfs(1,0);
        init();
        pre();
        while(q--)
        {
            int L,r;L = read(),r = read();
            printf("%lld\n",query(L,r));
        }
        system("pause");    
        return 0;
    }
    View Code
  • 相关阅读:
    【PAT】1001 害死人不偿命的(3n+1)猜想(动态更新)
    文件指令集
    近距离接触电脑
    文件管理
    文件写作方法
    文件读取方法
    打开文件的逻辑
    话术库
    max的逻辑
    抽象化指令
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13508906.html
Copyright © 2011-2022 走看看