zoukankan      html  css  js  c++  java
  • 暑假第八测

    题解:第一题:我写的指针线段树,但是被卡了, 但是数组线段树不会,因为不用建树

    这道题用并查集,从后往前染色,则不能覆盖,把一段颜色放在一个并查集中,O(N)的修改,我们让这段颜色的father指向他们这段的右端点,表示我下一次染色只能从右端点右边的一个开始;

    #include <bits/stdc++.h>
    const int M = 1000000 + 5;
    int n, k;
    using namespace std;
    int vis[M], lf[M], rg[M], c[M], fa[M];
    void read(int &x){
        x=0;int f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        x*=f;
    }
    
    int find(int a){
        if(fa[a]==a) return a;
        return fa[a]=find(fa[a]) ;
    }
    
    void uni(int a,int b){
        if(find(a)!=find(b)) fa[fa[a]]=fa[b] ;
    }
    void paint(int now, int co){
        vis[now] = co;
        if(now != 1 && vis[now-1])uni(now-1, now);
        if(now != n && vis[now+1])uni(now, now+1);
    }
    
    int main()
    {
        freopen("paint.in","r",stdin);
        freopen("paint.out","w",stdout);
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= k; i++)
            read(lf[i]), read(rg[i]), read(c[i]);
        for(int i = 1; i <= n; i++)fa[i] = i;
        for(int i = k; i >= 1; i--){
            int now = lf[i];
            while(now <= rg[i]){
                if(!vis[now]) paint(now, c[i]);
                now = find(now) + 1;
            }
        }
        for(int i = 1; i <= n; i++)printf("%d ", vis[i]);
        return 0;
    }
    View Code

    第二题:我们想的dp     dp[j][i] = max (dp[k][j] + 1) 如果i,j,k连成的线合法,我们只需要最后的两个点就好了;

    但是这样是N^3的, 过不了;我们想办法省去一维: dp[i] = max (dp[j] + 1),那我们必须保证转移到j的线再加上i-j这条线合法,构建

    凸壳的边满足的条件是:犄角递增; 我们N*N枚举边的犄角(cmath : atan2(vec.y, vec.x) )排序,按这个顺序建凸壳一定合法;我们用dp[i][j]表示以j结尾的凸壳边最多有多少条边; 更新它就用max  dp[?][i] ,维护一个桶,O(1),当再次来到i就构成了一个凸壳;

    #include <bits/stdc++.h>
    const int M = 100000 + 5;
    using namespace std;
    void read(int &x){
        x=0;int f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        x*=f;
    }
    struct Point{
        int x, y;
    }p[305];
    Point operator -(const Point &a, const Point &b){
        return (Point){a.x - b.x, a.y - b.y};
    }
    struct Edge{ double ang; int from, to;}G[300*300];
    bool cmp(Edge a, Edge b){return a.ang < b.ang;}
    int dp[305][305], tong[305];
    int main(){
     //   freopen("convex.in","r",stdin);
      //  freopen("convex.out","w",stdout);
        int n, tot = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)scanf("%d%d",&p[i].x, &p[i].y);
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                if(i != j){
                    Point tmp = p[j] - p[i];
                    G[++tot].ang = atan2(tmp.y, tmp.x);
                    G[tot].from = i;
                    G[tot].to = j;
                }
        sort(G+1, G+1+tot, cmp);
        int ans = 0;
        if(n <= 3){
            printf("%d
    ", n);
            return 0;
        }
        for(int h = 1; h <= n; h++){
            memset(dp, 0, sizeof(dp));
            memset(tong, 0x8f, sizeof(tong));
            tong[h] = 0;
            for(int i = 1; i <= tot; i++){
                int from = G[i].from, to = G[i].to;
                dp[from][to] = tong[from] + 1;
                tong[to] = max(tong[to], dp[from][to]);
                //printf("%d %d %d %d %d
    ", i, dp[from][to], from, to, tong[to]);
            }
            ans = max(ans, tong[h]);
        }
    
        printf("%d
    ",ans);
    }
    View Code

    第三题:贪心+dp

    首先电视连续与不连续与他们排在任何一种种类后面没有关系, 所以我们把一个种类放在一起;对于连续与不连续的电视节目其实就是看他们分成了几段,如果分成3段,我们就会有3个b的收益,所以我们选3个最大的b, 剩下的a贪心要最大的;就可以预处理出每种颜色分成k段的最大收益;

    dp[i][k]表示考虑了前i种电视分成了k段的最大收益,限制是什么,对于单个电视分的段数 <= ceil(k /2);以下是std

    /*
     * m.cpp
     *
     *  Created on: Oct 28, 2013
     *      Author: acm
     */
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <string>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int MAX_N = 600 + 10, INF = ~0U >> 2;
    
    struct TV {
        int t, a, b;
        int id;
    
        void read(int id) {
            this->id = id;
            cin >> t >> a >> b;
        }
    
        bool operator<(const TV&o) const {
            return b - a > o.b - o.a;
        }
    };
    
    struct TVSet {
        vector<TV> a;
    
        void add(TV o) {
            a.push_back(o);
        }
    
        vector<int> maxret;
        int color, n;
    
        vector<vector<int> > dp, how;
    
        void update(int i, int j, int hw, int c) {
    //        cout << i << " " << j << " " << c << " " << dp[i][j] << endl;
            if (c > dp[i][j]) {
                dp[i][j] = c;
                how[i][j] = hw;
            }
        }
    
        void doit() {
            n = a.size();
            color = a[0].t;
            dp.assign(n + 1, vector<int>(n + 1, -INF));
            how.assign(n + 1, vector<int>(n + 1));
    
            sort(a.begin(), a.end());
    
            dp[0][0] = 0;
            for (int i = 0; i < n; ++i) {
                TV me = a[i];
                for (int j = 0; j <= n; ++j) {
                    int c = dp[i][j];
    //                cout << i << " " << j << " " << c << endl;
                    if (c == -INF)
                        continue;
                    if (j > 0)
                        update(i + 1, j, 0, c + me.a);
                    update(i + 1, j + 1, 1, c + me.b);
                    update(i + 1, j, -1, c);
                }
            }
    
            maxret.assign(n + 1, 0);
            for (int i = 0; i <= n; ++i) {
                maxret[i] = dp[n][i];
    //            cerr << maxret[i] << endl;
            }
        }
    
        vector<vector<TV> > chains;
    
        void buildIt(int k) {
            chains.clear();
            int i = n, j = k;
    
            vector<pair<int, TV> > op;
    
            while (i > 0) {
                if (how[i][j] == -1) {
                    --i;
                    continue;
                }
                if (how[i][j] == 0) {
                    op.push_back(make_pair(0, a[i - 1]));
                    --i;
                    continue;
                }
                if (how[i][j] == 1) {
                    op.push_back(make_pair(1, a[i - 1]));
                    --i, --j;
                    continue;
                }
            }
    
            int chk = 0;
            for (int i = 0; i < op.size(); ++i) {
                pair<int, TV> t = op[op.size() - 1 - i];
    //            cerr << t.second.id << endl;
                if (t.first == 0) {
                    chains[0].push_back(t.second);
                    chk += t.second.a;
                } else {
                    chains.push_back(vector<TV>());
                    chains.back().push_back(t.second);
                    chk += t.second.b;
                }
            }
    //        cout << chk << " " << maxret[k] << endl;
    //        cout << chains.size() << " " << k << endl;
        }
    
        bool operator<(const TVSet&o) const {
            return a.size() < o.a.size();
        }
    };
    
    TVSet set[MAX_N];
    
    int n;
    
    vector<TVSet> tvsets;
    
    vector<vector<vector<int> > > dp;
    
    int main() {
        freopen("tv.in","r",stdin);
        freopen("tv.out","w",stdout);
        cin >> n;
        for (int i = 0; i < n; ++i) {
            TV t;
            t.read(i);
            --t.t;
            set[t.t].add(t);
        }
    
        for (int i = 0; i < n; ++i) {
            if (set[i].a.size()) {
                tvsets.push_back(set[i]);
            }
        }
    
        sort(tvsets.begin(), tvsets.end());
    
        for (int i = 0; i < tvsets.size(); ++i) {
            tvsets[i].doit();
        }
    
        dp.resize(tvsets.size() + 1);
        
        dp[0] = vector<vector<int> >(1, vector<int>(1, 0));
    
    //    dp[0][0][0] = 0;
        int curSum = 0, curMax = 0;
    
        for (int i = 0; i < tvsets.size(); ++i) {
            int nextSum = curSum + tvsets[i].n;
            int nextMax = tvsets[i].n;
            if(i>0)
                dp[i-1].clear();
    
            dp[i + 1] = vector<vector<int> >(nextSum + 1,
                    vector<int>(nextMax + 1, -INF));
    
            TVSet&set = tvsets[i];
    
            for (int j = 0; j <= curSum; ++j) {
                for (int k = 0; k <= curMax; ++k) {
                    int c = dp[i][j][k];
                    if (c == -INF)
                        continue;
                    for (int me = 0; me <= set.n; ++me) {
                        int nc = c + set.maxret[me];
                        int nk = max(me, k);
                        if (nc > dp[i + 1][j + me][nk]) {
                            dp[i + 1][j + me][nk] = nc;
                        }
                    }
                }
            }
    
            curSum = nextSum, curMax = nextMax;
        }
    
        int best = 0;
    
        for (int j = 0; j <= curSum; ++j) {
            for (int k = 0; k <= curMax; ++k)
                if (k + k - 1 <= j) {
                    if (dp[tvsets.size()][j][k] > best) {
                        best = dp[tvsets.size()][j][k];
                    }
                }
        }
    
        cout << best << endl;
    }
    View Code
  • 相关阅读:
    vue-cli3.0
    windows服务器的误解
    redis实现消息队列-java代码实现
    Docker 修改容器内的时区
    Spring boot项目分环境Maven打包,动态配置文件,动态配置项目
    rsa公钥和私钥到底哪个才是用来加密,哪个用来解密?
    session和cookie的区别和联系详解,Cookie Session相关看这篇就够了。
    面试中的nginx高可用高并发!
    js正则表达式验证、匹配数字、匹配字符串、匹配中文、匹配任意字符备忘录
    thymeleaf模板、thymeleaf语法相关中文文档教程
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9373689.html
Copyright © 2011-2022 走看看