zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Android_NDK问题:APP_BUILD_SCRIPT points to an unknown file: <project_path>/jni/Android.mk
    Android开发问题集锦-Button初始为disable状态时自定义的selector不生效问题
    一步步学习Python-django开发-添加后台管理
    一步步学习Python-django开发-建立django数据库
    一步步学习Python-django开发-Mac下搭建Python-Django环境
    JAVA小知识点-Finally和Return的执行关系
    Android自定义组合控件内子控件无法显示问题
    《将博客搬至CSDN》
    idea自动生成try/catch代码块的快捷键
    转:Apache common包 CollectionUtils 使用详解
  • 原文地址:https://www.cnblogs.com/babydragon/p/11725009.html
Copyright © 2011-2022 走看看