zoukankan      html  css  js  c++  java
  • 7.29总结当日


    今天排名一般,但是却感觉不错,也是可以的


    7.29场链接
    A题:
    题意:01背包问题,要求最优情况是重量和体积都最大的情况

    解法:和之前的“劲歌金曲”那道题挺像的,就是设计一个最优状态,只有当这个状态比当前状态更优的时候我们才进行状态转移,状态这个词最为重要
    注意压缩完空间后的最终状态所处的位置

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int w[1005], v[1005];
    typedef long long ll;
    struct node {
        int w, v;
        bool operator < (const node & rhs)const  {
            return w < rhs.w || (w == rhs.w&&v < rhs.v);
        }
    }dp[100005];
    
    int main() {
        int T; scanf("%d", &T);
        while (T--) {
            int n, c; scanf("%d%d", &n, &c);
            memset(dp, 0, sizeof(dp));
            for (int i = 1; i <= n; i++)scanf("%d", &w[i]);
            for (int j = 1; j <= n; j++)scanf("%d", &v[j]);
    
            for (int i = 1; i <= n; i++) {
                for (int j = c; j >= v[i]; j--) {
                    node tmp;
                    tmp.v = dp[j - v[i]].v + v[i];
                    tmp.w = dp[j - v[i]].w + w[i];
                    if (dp[j] < tmp)dp[j] = tmp;
                }
            }
            printf("%d %d
    ", dp[c].w, dp[c].v);
        }
        return 0;
    }

    D题:
    题意:有n堆石子,每次要求把重量最小的两堆进行合并,之后会有m个询问,问第几次操作完中某堆石子的序号

    解法:
    哈夫曼树,并查集,因为当这个石子和其他石子合并的时候,他们就相当于属于一个集合了,那么之后对集合中一个元素的修改就相当于修改其所有的元素

    #include<cstdio>
    #include<queue>
    #include<functional>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    int set[1000000];
    
    int findSet(int x) {
        if (x == set[x]) return x;
        else return set[x] = findSet(set[x]);
    }
    
    void unionSet(int x, int y) {//将y设置为x的父亲
        int fx = findSet(x);
        int fy = findSet(y);
        if (fx != fy) {
            set[fx] = fy;
        }
    }
    
    struct node {
        ll w;
        int id;
        bool operator < (const node& rhs)const {
            return w > rhs.w || (w == rhs.w&&id > rhs.id);
        }
    };
    priority_queue <node> q;
    queue<pair<int, int>>ask;
    
    int main() {
        int T; scanf("%d", &T);
        while(T--){
            while (!q.empty())q.pop();
            while (!ask.empty())ask.pop();
            memset(set, 0, sizeof(set));
            int n, m; scanf("%d%d", &n, &m);
            ll tmp;
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &tmp);
                q.push(node{ tmp,i });//编号为i的稀泥的重量为tmp
                set[i] = i;
            }
            for (int i = 1; i <= m; i++) {
                pair<int, int>tmp;
                scanf("%d%d", &tmp.first, &tmp.second);
                ask.push(tmp);
            }
            int now = 0;
            while (ask.size()&&q.size() > 1) {
                node x1 = q.top(); q.pop();
                node x2 = q.top(); q.pop();
                if (x1.id > x2.id)swap(x1.id, x2.id);
                unionSet(x2.id, x1.id);
                q.push(node{ x1.w + x2.w,findSet(x1.id) });
                now++;
                while (ask.size()&&now == ask.front().first) {
                    printf("%d
    ", findSet(ask.front().second));
                    ask.pop();
                }
            }
        }
        return 0;
    }

    codeforces contest 1009
    B题:
    题意:给定一个数列,这个数列里面只有0,1,2,有两种操作,将相邻的01对换位置,将相邻的12调换位置,2和0不能调换位置,每种操作可以变无数次,问经过多种这样子的操作后字典序最小的序列是什么样子的。

    解法:由于2和0的位置是不能调换的,所以我们就把所有的1单独拿出来,然后再把所有的1放到第一个2前面就行了,很好的思路题

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    char s[100000 + 5];
    
    int main() {
        scanf("%s", s);
        int len = strlen(s), pos=-1, num = 0;
        for (int i = 0; i < len; i++) {
            if (s[i] == '2'&& pos==-1) pos = i;
            if (s[i] == '1') { num++; s[i] = '#'; }
        }
        for (int i = 0; i < len; i++) {
            if (s[i] == '#')continue;
            if (i == pos)for (int k = 0; k < num; k++)printf("1");
            printf("%c", s[i]);
        }
        if(pos==-1)for (int k = 0; k < num; k++)printf("1");
        return 0;
    }

    C题:
    题意:给定一个序列,每次给你两个数,要求将序列里面的每个数都加上x,之后选择一个位置j,将所有的数加上d*dist(i,j),问怎样选择j可以使得最后所有的数的平均数最大

    解法:推一下公式就行了,要注意的是double的用法

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int a[100000 + 5];
    
    int main() {
        ll n, m; scanf("%I64d%I64d", &n, &m);
        ll x, d, pos;
        ll ans = 0;
        for (int i = 0; i < m; i++) {
            scanf("%I64d%I64d", &x, &d);
            ans += ll(n)*x;
            if (d > 0) { ans += d *n*(n - 1) / 2; }
            else ans += d*(n - (n + 1) / 2)*((n + 1) / 2);
        }
        printf("%.15f
    ", double(ans)/n);
        return 0;
    }
  • 相关阅读:
    Java 处理cookie的方法
    HTML5的新标签-整体布局
    Git学习文档——文件状态git status
    Css中路径data用法
    python2
    hangfire
    Nginx系列~Nginx服务启动不了
    git形成本地仓库并从远处url拉取
    orcal和sql server中的字符串查找函数
    Eclipse 修改项目名称
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489798.html
Copyright © 2011-2022 走看看