• codeforces1249-div3


    A

    B

    C

    等比数列的性质,前面的i项的和,不会超过第i+1

    D

    有若干个区间,要求每一个点被区间覆盖的次数不能超过k个。问移除的最少的区间的数目。

    贪心:
    若某个点被覆盖了k次以上,那么肯定是移除这些区间里面右端点最右的点的区间。
    时间复杂度要求是(O(nlog(n)))

    模拟就好了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<bitset>
     
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    #define pb(x) push_back(x)
    #define cls(x, val) memset(x, val, sizeof(x))
    #define fi first
    #define se second
    #define mp(x, y) make_pair(x, y)
    #define inc(i, l, r) for(int i=l; i<=r; i++)
    const int inf = 0x3f3f3f3f;
    const int maxn = 2e5+10;
    int l[maxn], r[maxn];
    int n, k;
    vector<int> node[maxn];
    set<pii> s;
     
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>k;
        for(int i=1; i<=n; i++){
            cin>>l[i]>>r[i];
            node[l[i]].push_back(i);
            node[r[i]+1].push_back(-i);
        }
        vector<int> ans;
        for(int i=1; i<=2e5; i++){
            for(int j=0; j<node[i].size(); j++){
                int u = node[i][j];
                if(u>0){
                    s.insert(mp(r[u], u));
                }
                else s.erase(mp(r[-u], -u));
            }
            while(s.size()>k){
                set<pii>::iterator it = s.end();
                --it;
                ans.push_back(it->se);
                s.erase(*it);
            }
        }
        cout<<ans.size()<<endl;
        for(int i=0; i<ans.size(); i++){
            cout<<abs(ans[i])<<" ";
        }
        cout<<endl;
     
        return 0;
    }
     
    

    E

    简单dp

    F

    题目:
    要求一个点的集合,使得他们之间的任意两点之间的距离大于k,并且这个集合的点的权重和最大
    树形dp
    学习了一种很trick的写法,不具有普遍性

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200 + 10;
    
    vector<int> G[maxn];
    int n, k, m;
    int a[maxn], vis[maxn];
    void dfs(int u, int fa, int d){
       if(d > k) return ;
       a[u] -= m;
       for(int &v : G[u]) if(v != fa) dfs(v, u, d + 1);
    }
    int main(){
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i++) scanf("%d", a + i);
        for(int i = 1; i < n; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        queue<int> q;
        vector<int> b;
        q.push(1); vis[1] = 1;
        while(!q.empty()){
            int u = q.front(); q.pop();
            b.push_back(u);
            for(int &v : G[u]){
                if(!vis[v]){
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
        int ans = 0;
        for(int i = b.size() - 1; i >= 0; i--){
            //这里写的很trick, 从叶子节点开始取。若上面有更好的选择,那么相当于就叶子的贡献转移到上面了。
            m = a[b[i]];
            if(m < 0) continue;
            ans += m;
            dfs(b[i], 0, 0);
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    

    树形dp的写法有点像另外的一个题目:
    给一个树形的结构,然后任意一个节点到关键节点的距离不能超过k。
    问最小的关键节点的数目。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 210;
    
    int n, k;
    vector<int> a;
    vector<vector<int>> g, dp;
    
    void dfs(int v, int p) {
    	dp[v][0] = a[v];
    	for (auto to : g[v]) {
    		if (to != p) dfs(to, v);
    	}
    	for (int dep = 0; dep < N; ++dep) {
    		if (dep == 0) {
    			for (auto to : g[v]) {
    				if (to == p) continue;
    				dp[v][dep] += dp[to][max(0, k - dep - 1)];
    			}
    		} else {
    			for (auto to : g[v]) {
    				if (to == p) continue;
    				int cur = dp[to][dep - 1];
    				for (auto other : g[v]) {
    					if (other == p || other == to) continue;
    					cur += dp[other][max(dep - 1, k - dep - 1)];
    				}
    				dp[v][dep] = max(dp[v][dep], cur);
    			}
    		}
    	}
    	for (int dep = N - 1; dep > 0; --dep) {
    		dp[v][dep - 1] = max(dp[v][dep - 1], dp[v][dep]);
    	}
    }
    
    int main() {
    #ifdef _DEBUG
    	freopen("input.txt", "r", stdin);
    //	freopen("output.txt", "w", stdout);
    #endif
    	
    	cin >> n >> k;
    	++k;
    	a = vector<int>(n);
    	for (int i = 0; i < n; ++i) {
    		cin >> a[i];
    	}
    	g = vector<vector<int>>(n);
    	for (int i = 0; i < n - 1; ++i) {
    		int x, y;
    		cin >> x >> y;
    		--x, --y;
    		g[x].push_back(y);
    		g[y].push_back(x);
    	}
    	
    	dp = vector<vector<int>>(n, vector<int>(N));
    	dfs(0, -1);
    	cout << dp[0][0] << endl;
    	
    	return 0;
    }
    
  • 相关阅读:
    《大话数据结构》第1章 数据结构绪论 1.2 你数据结构怎么学的?
    伍迷七八月新浪微博集锦
    《大话数据结构》第9章 排序 9.7 堆排序(下)
    《大话数据结构》第3章 线性表 3.8.2 单链表的删除
    《大话数据结构》第9章 排序 9.5 直接插入排序
    《大话数据结构》第9章 排序 9.8 归并排序(上)
    《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度
    《大话数据结构》第1章 数据结构绪论 1.1 开场白
    《大话数据结构》第9章 排序 9.1 开场白
    [AWS] Assign a public IP address to an EC2 instance after launched
  • 原文地址:https://www.cnblogs.com/babydragon/p/11725009.html
Copyright © 2020-2023  润新知