• 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
    ");
        }else {
            printf("%d
    ",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
    ");
        }else {
            printf("%d
    ",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
    ",max(dp[1][0],dp[1][1]));
      }
      return 0;
    }
  • 相关阅读:
    webpack源码学习总结
    并发容器(三)非阻塞队列的并发容器
    并发容器(二)阻塞队列详细介绍
    并发容器(一)同步容器 与 并发容器
    java内存模型(二)深入理解java内存模型的系列好文
    java内存模型(一)正确使用 Volatile 变量
    原子操作类(二)原子操作的实现原理
    原子操作类(一)原子操作类详细介绍
    同步锁源码分析(一)AbstractQueuedSynchronizer原理
    并发工具类(五) Phaser类
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11637692.html
Copyright © 2020-2023  润新知