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 }