zoukankan      html  css  js  c++  java
  • Codeforces Round #378(div 2)

    A、B:=w=

    C:

      题意:给你一个a数组和b数组,a数组中大的数可以吃掉小的数并且给它加上吃掉的数,问能否达到b数组的状态,如果可以输出方案

      分析:首先肯定想到分块,于是子问题就是判断一段数能否吃干净

         可以找到这段数之间的最大值,从这个最大值开始吃一边,再反向吃,特判一些特殊的情况

         O(n)的

    D:

      题意:给定n个长方体,求一个最大的内切球的半径,可以是两块石头将两个完全匹配的面合起来的或者就用一块石头,输出切出最大内切球的那1/2个石头是哪些

      分析:因为一个长方体的最大的内切球半径是三个边长的最小值,所以拼接的时候也是加长最小边最优,所以可以先把每个长方体三个边长从小到大排序,再对所有的长方体排序,扫一遍再判定。

    E:占坑

    F:

      题意:n点m条边的无向联通图,n,m<=200000,你有s元钱,每条边花费c[i]元钱减去单位1长度(边可以为负数),问操作之后的最小生成树

      分析:减去单位1长度,最好的情况就是ans-=1,也就是说,减去的不应该分配给多条边,这样不好,最好就是给一条边尽可能减去更多的长度

         想到可以枚举每条边i,让它尽可能减(可以为负数,所以很OK),然后求目前的最小生成树。

         如果这条边就是在初始的最小生成树的上,那么就直接把ans减掉

         如果这条边不在的话,那么可以找到其两个端点,即求最小生成树上的两点之间的最大值,将那条边删掉,换成这条边,比较最小生成树的值

         因为要输出方案,所以处理细节极其多且麻烦,这里需要贴上代码……

         
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=2e5;
      4 vector<int> g[maxn+50],g1[maxn+50];
      5 struct wjmzbmr
      6 {
      7     int from,to,id;
      8     long long w;
      9     bool operator < (const wjmzbmr& x) const
     10     {
     11         return w<x.w;
     12     }
     13 };
     14 wjmzbmr edge[2*maxn+50],e[2*maxn+50],E[2*maxn+50];
     15 long long w[maxn+50],c[maxn+50],money;
     16 long long dp[maxn+50][20],dpmax[maxn+50][20];
     17 bool p[maxn+50];
     18 int father[maxn+50][20];
     19 int f[maxn+50],d[maxn+50];
     20 int n,m;
     21 long long maxg,maxw;
     22 long long ans=0;
     23 int findfather(int k)
     24 {
     25     if(f[k]!=k) return f[k]=findfather(f[k]);else return k;
     26 }
     27 void dfs(int k,int last)
     28 {
     29     for(int i=0;i<g1[k].size();++i)
     30     {
     31         wjmzbmr u=e[g1[k][i]];
     32         if(u.to==last) continue;
     33         father[u.to][0]=k;
     34         dp[u.to][0]=u.w;
     35         dpmax[u.to][0]=u.id;
     36         d[u.to]=d[k]+1;
     37         dfs(u.to,k);
     38     }
     39 }
     40 void lca(int x,int y)
     41 {
     42     maxw=0;
     43     if(d[x]<d[y]) swap(x,y);
     44     int deep=d[x]-d[y];
     45     for(int i=0;i<20;++i)
     46         if(deep&(1<<i))
     47         {
     48             if(dp[x][i]>maxw) maxw=dp[x][i],maxg=dpmax[x][i];
     49             x=father[x][i];
     50         }
     51     for(int i=19;i>=0;--i)
     52         if(father[x][i]!=father[y][i])
     53         {
     54             long long m=dp[x][i],t=dpmax[x][i];
     55             if(dp[y][i]>dp[x][i]) m=dp[y][i],t=dpmax[y][i];
     56             if(m>maxw) maxw=m,maxg=t;
     57             x=father[x][i],y=father[y][i];
     58         }
     59     if(x==y) return;
     60     int i=0;
     61     long long m=dp[x][i];
     62     long long t=dpmax[x][i];
     63     if(dp[y][i]>dp[x][i]) m=dp[y][i],t=dpmax[y][i];
     64     if(m>maxw) maxw=m,maxg=t;
     65     x=father[x][i],y=father[y][i];
     66     return ;
     67 }
     68 int main()
     69 {
     70     scanf("%d %d",&n,&m);
     71     for(int i=1;i<=m;++i) scanf("%lld",&w[i]);
     72     for(int i=1;i<=m;++i) scanf("%lld",&c[i]);
     73     for(int i=0;i<=n;++i) g[i].clear(),g1[i].clear();
     74     for(int i=0;i<m;++i)
     75     {
     76         int x,y;
     77         scanf("%d %d",&x,&y);
     78         e[i*2]=(wjmzbmr){x,y,i+1,w[i+1]},e[i*2+1]=(wjmzbmr){y,x,i+1,w[i+1]};
     79         g[x].push_back(i*2),g[y].push_back(i*2+1);
     80         edge[i+1]=(wjmzbmr){x,y,i+1,w[i+1]};
     81         E[i+1]=edge[i+1];
     82     }
     83     scanf("%lld",&money);
     84     sort(edge+1,edge+m+1);
     85     for(int i=1;i<=n;++i) f[i]=i;
     86     memset(p,0,sizeof(p));
     87     for(int i=1;i<=m;++i)
     88     {
     89         int x=findfather(edge[i].from),y=findfather(edge[i].to);
     90         if(x==y) continue;
     91         f[y]=x;
     92         ans+=edge[i].w;
     93         p[edge[i].id]=true;
     94         g1[edge[i].from].push_back((edge[i].id-1)*2),g1[edge[i].to].push_back((edge[i].id-1)*2+1);
     95     }
     96     memset(father,0,sizeof(father));
     97     memset(d,0,sizeof(d));
     98     memset(dp,0,sizeof(dp));
     99     dfs(1,0);
    100     for(int i=1;i<20;++i)
    101         for(int j=1;j<=n;++j)
    102         {
    103             father[j][i]=father[father[j][i-1]][i-1];
    104             dp[j][i]=dp[j][i-1],dpmax[j][i]=dpmax[j][i-1];
    105             if(dp[father[j][i-1]][i-1]>dp[j][i-1])
    106             {
    107                 dp[j][i]=dp[father[j][i-1]][i-1];
    108                 dpmax[j][i]=dpmax[father[j][i-1]][i-1];
    109             }
    110         }
    111     long long s=ans;
    112     long long xx,yy,zz;
    113     bool flag=0;
    114     for(int i=1;i<=m;++i)
    115     {
    116         wjmzbmr u=E[i];
    117         if(p[i])
    118         {
    119             if(s-money/c[i]>=ans) continue;
    120             ans=s-money/c[i];
    121             xx=i,yy=u.w-money/c[i];
    122             flag=0;
    123         }
    124         else
    125         {
    126             lca(u.from,u.to);
    127             wjmzbmr v=E[maxg];
    128             if(s-maxw+w[i]-money/c[i]>=ans) continue;
    129             ans=s-maxw+w[i]-money/c[i];
    130             xx=i,yy=w[i]-money/c[i],zz=v.id;
    131             flag=1;
    132         }
    133     }
    134     printf("%lld
    ",ans);
    135     if(!flag)
    136     {
    137         for(int i=1;i<=m;++i)
    138             if(p[i])
    139                 if(i==xx) printf("%d %lld
    ",i,yy);
    140                 else printf("%d %lld
    ",i,E[i].w);
    141     }
    142     else
    143     {
    144         for(int i=1;i<xx;++i)
    145             if(p[i]&&i!=zz) printf("%d %lld
    ",i,E[i].w);
    146         printf("%lld %lld
    ",xx,yy);
    147         for(int i=xx+1;i<=m;++i)
    148             if(p[i]&&i!=zz) printf("%d %lld
    ",i,E[i].w);
    149 
    150     }
    151     return 0;
    152 }
    View Code
  • 相关阅读:
    MarkDown语法总结
    HashMap
    [LeetCode] 102. Binary Tree Level Order Traversal(二叉树的中序遍历)
    [LeetCode] 287. Find the Duplicate Number(寻找重复数字)
    [LeetCode] 215. Kth Largest Element in an Array(数组里的第 k 大元素)
    [LeetCode] 39. Combination Sum(组合的和)
    [LeetCode] 49. Group Anagrams(分组相同字母异序词)
    [LeetCode] 48. Rotate Image(旋转图片)
    [LeetCode] 647. Palindromic Substrings(回文子串)
    [LeetCode] 238. Product of Array Except Self(数组除自身元素外的乘积)
  • 原文地址:https://www.cnblogs.com/wmrv587/p/6075125.html
Copyright © 2011-2022 走看看