Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) 题解

A..B略

C 对当前的值排序,再二分答案,然后对于(i%x==0 && i%y==0)放入大的,再放其他的贪心解决即可。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#define LL long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxx = 2e5+7;
int a[maxx];
int vis[maxx];
LL k;
LL aa,bb;
int x,y,n;
bool check(int mid){
      LL ans=0;
      int top=0;
       for (int i=1;i<=mid;i++){
            if (i%x==0 && i%y==0){
                vis[i]=a[++top];
                ans=(LL)ans+vis[i]/100*(aa+bb);
            }else {
                vis[i]=0;
            }

        }
        for (int i=1;i<=mid;i++){
            if (i%y==0 && !vis[i]){
                vis[i]=a[++top];
                ans=(LL)ans+vis[i]/100*bb;
            }

        }
        for (int i=1;i<=mid;i++){
            if (i%x==0 && !vis[i]){
                vis[i]=a[++top];
                ans=(LL)ans+vis[i]/100*aa;
            }
        }
        return ans>=k;
}
bool cmp(int x,int y){
   return x>y;
}
int main(){
  int t;
  scanf("%d",&t);
  while(t--){
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
      scanf("%d",&a[i]);
    }
    scanf("%d%d",&aa,&x);
    scanf("%d%d",&bb,&y);
    scanf("%lld",&k);
    if (aa>bb){
        swap(x,y);
        swap(aa,bb);
    }
    sort(a+1,a+1+n,cmp);
    int l=1;
    int r=n;
    int ans=-1;
    while(l<=r){
        int mid=(l+r)>>1;
        if (check(mid)){
            ans=mid;
            r=mid-1;
        }else {
            l=mid+1;
        }
    }
    if (ans==-1){
        printf("-1\n");
    }else {
        printf("%d\n",ans);
    }
  }
  return 0;
}

D 记录一次出现和最后一次出现的,考虑移动的比较麻烦,我们可以考虑对于两个相邻的大小的值,前面那个值最后次出现的位置是大于这个值第一次出现的,那么他们的相对位置关系是不用移动的,我们求出这种不用移动的相对位置连续个数是最多的,那么就是最长不用移动的,其他的肯定要移动,那么直接用所有值的个数去减这个值就行了。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#define LL long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxx = 2e5+7;
int a[maxx];
int vis[maxx];
LL k;
LL aa,bb;
int x,y,n;
bool check(int mid){
      LL ans=0;
      int top=0;
       for (int i=1;i<=mid;i++){
            if (i%x==0 && i%y==0){
                vis[i]=a[++top];
                ans=(LL)ans+vis[i]/100*(aa+bb);
            }else {
                vis[i]=0;
            }

        }
        for (int i=1;i<=mid;i++){
            if (i%y==0 && !vis[i]){
                vis[i]=a[++top];
                ans=(LL)ans+vis[i]/100*bb;
            }

        }
        for (int i=1;i<=mid;i++){
            if (i%x==0 && !vis[i]){
                vis[i]=a[++top];
                ans=(LL)ans+vis[i]/100*aa;
            }
        }
        return ans>=k;
}
bool cmp(int x,int y){
   return x>y;
}
int main(){
  int t;
  scanf("%d",&t);
  while(t--){
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
      scanf("%d",&a[i]);
    }
    scanf("%d%d",&aa,&x);
    scanf("%d%d",&bb,&y);
    scanf("%lld",&k);
    if (aa>bb){
        swap(x,y);
        swap(aa,bb);
    }
    sort(a+1,a+1+n,cmp);
    int l=1;
    int r=n;
    int ans=-1;
    while(l<=r){
        int mid=(l+r)>>1;
        if (check(mid)){
            ans=mid;
            r=mid-1;
        }else {
            l=mid+1;
        }
    }
    if (ans==-1){
        printf("-1\n");
    }else {
        printf("%d\n",ans);
    }
  }
  return 0;
}

E. Paint the Tree

我们考虑dp[i][0]代表这个节点的k重颜色已经全部匹配,dp[i][0代表当前节点还有颜色没有匹配。那么我们其实可以很容易得到dp的转移

首先dp[i][1]+=sigma[son[i]][0] dp[i][0]+=sigma[son[i]][0] 也就是说我们每个节点首先看出全部选了子树颜色已经全部匹配的结果

我们再把所有节点选择子树没有匹配完全的加上这条路径的长度去减去子树已经匹配的完全的差值,然后再差值中选中前k大的正数和加到dp[i][0]表示选择后悔了

把前i-1的正数加到dp[i][1]中即可。最后取根节点两者的最大值即可。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int maxx = 5e5+6;
int ver[maxx*2],edge[2*maxx],head[maxx],Next[2*maxx];
int n,k,tot;
LL dp[maxx][2];
void add(int x,int y,int w){
   ver[++tot]=y;edge[tot]=w;Next[tot]=head[x];head[x]=tot;
   ver[++tot]=x;edge[tot]=w;Next[tot]=head[y];head[y]=tot;
}
bool cmp(int a,int b){
   return a>b;
}
void dfs(int u,int fa){
   dp[u][0]=dp[u][1]=0;
   vector<int>vv;
   vv.clear();
   for (int i=head[u];i;i=Next[i]){
       int v=ver[i];
       if (v==fa)continue;
       dfs(v,u);
       dp[u][0]+=dp[v][0];
       dp[u][1]+=dp[v][0];
   }
   for (int i=head[u];i;i=Next[i]){
       int v=ver[i];
       if (v==fa)continue;
       vv.push_back(dp[v][1]+edge[i]-dp[v][0]);
   }
   sort(vv.begin(),vv.end(),cmp);
   int sz=min((int)vv.size(),k);
   for (int i=0;i<sz;i++){
       if(vv[i]<0)break;
       if(i==k-1){
          dp[u][0]=(LL)vv[i]+dp[u][1];
       }else {
          dp[u][0]=(LL)vv[i]+dp[u][1];
          dp[u][1]=(LL)vv[i]+dp[u][1];
       }
   }
}
int main(){
  int t;
  scanf("%d",&t);
  int uu,vv,ww;
  while(t--){
     scanf("%d%d",&n,&k);
     for (int i=1;i<=n;i++){
        head[i]=0;
     }
     for (int i=1;i<=n-1;i++){
        scanf("%d%d%d",&uu,&vv,&ww);
        add(uu,vv,ww);
     }
     dfs(1,-1);
     printf("%lld\n",max(dp[1][0],dp[1][1]));
  }
  return 0;
}

原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11637692.html

时间: 2024-11-14 19:06:38

Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) 题解的相关文章

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3

A,有多个线段,求一条最短的线段长度,能过覆盖到所又线段,例如(2,4)和(5,6) 那么我们需要4 5连起来,长度为1,例如(2,10)(3,11),用(3,10) 思路:我们想一下如果题目说的是最长我们肯定是取最小x和最大的y连起来就完事. 但是要求长度最小又得覆盖,那么可以这样想,我们需要把最小的x不断右移到这条线段的y, 最大的左移到x,所以就是最大x-最小y完事 #include <bits/stdc++.h> using namespace std; #define ll long

【cf比赛记录】Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4)

比赛传送门 只能说当晚状态不佳吧,有点头疼感冒的症状.也跟脑子没转过来有关系,A题最后一步爆搜没能立即想出来,B题搜索没有用好STL,C题也因为前面两题弄崩了心态,最后,果然掉分了. A:简单数学 B:数学+排序 C:字符串搜索 A // https://codeforces.com/contest/1277/problem/A /* 题意: 给出一个数,求不大于该数的完美整数的个数(完美整数指全是一个数组成的数字,如:111, 333333, 444444, 9, 8888 ...) 分析:

Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2)

B2 - TV Subscriptions (Hard Version) 遍历,维护一个set和set<pair<int,int>>即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6+7; 5 const ll mod = 1e9 + 9; 6 #define afdafafafdafaf y1; 7 int ar[maxn]

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C. Messy 构造

C. Messy You are fed up with your messy room, so you decided to clean it up. Your room is a bracket sequence s=s1s2-sn of length n. Each character of this string is either an opening bracket '(' or a closing bracket ')'. In one operation you can choo

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B. Box 贪心

B. Box Permutation p is a sequence of integers p=[p1,p2,-,pn], consisting of n distinct (unique) positive integers between 1 and n, inclusive. For example, the following sequences are permutations: [3,4,1,2], [1], [1,2]. The following sequences are n

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) F2. Wrong Answer on test 233 (Hard Version) dp 数学

F2. Wrong Answer on test 233 (Hard Version) Your program fails again. This time it gets "Wrong answer on test 233" . This is the harder version of the problem. In this version, 1≤n≤2?105. You can hack this problem if you locked it. But you can h

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心

D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, 1≤n,m≤2?105. You can hack this problem if you locked it. But you can hack the previous problem only if you locked both problems. You are given a seque

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) A Math Problem

//只要从所有区间右端点的最小值覆盖到所有区间左端点的最大值即可 #include<iostream> using namespace std ; int x,y; int n; int t; int main() { cin>>t; while(t--) { cin>>n; if(n==1) { cin>>x>>y; cout<<0<<endl; } else { int l=0,r=1e9+10; for(int i=

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B Box

#include<bits/stdc++.h> using namespace std; int shu[100005]; int ans[100005]; int main() { int total; cin>>total; while(total--) { int n; bool flag=true; cin>>n; unordered_set<int>tree; set<int>num; for(int i=1; i<=n; i++