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\n",ans);
135     if(!flag)
136     {
137         for(int i=1;i<=m;++i)
138             if(p[i])
139                 if(i==xx) printf("%d %lld\n",i,yy);
140                 else printf("%d %lld\n",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\n",i,E[i].w);
146         printf("%lld %lld\n",xx,yy);
147         for(int i=xx+1;i<=m;++i)
148             if(p[i]&&i!=zz) printf("%d %lld\n",i,E[i].w);
149 
150     }
151     return 0;
152 }
View Code

 

posted @ 2016-11-17 19:20  Chellyutaha  阅读(147)  评论(0编辑  收藏  举报