练习题
背包(2020-06-14)
集排序,贪心,前缀和,二分的很综合的题
题目描述
Applese有1个容量为v的背包,有n个物品,每一个物品有一个价值ai,以及一个大小bi
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
输入描述:
第一行三个数v, n, m,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数ai,bi,分别代表物品价值以及大小
n ≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ v
输出描述:
仅一行,代表最大的中位数
示例1
输入
20 5 3 3 5 5 6 8 7 10 6 15 10
输出
8
m为奇数的情况下
然后我们枚举每个位置,如果该位置是中位数的最大,那么这个位置前面选m/2个的重量加上后面m/2个重量,使他们小于V就说明这个位置可以取得的,只需要维护一个大小为m/2 的堆就行,每次pop掉堆中最大的
m为偶数的时候同理
但是中间需要选择两个位置,数据范围为1e5,n^2肯定不行,所以用nlogn的算法,可以枚举第一个位置,二分第二个位置
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read() 4 { 5 int x=0;char c=getchar(); 6 for(;!isdigit(c);c=getchar()); 7 for(;isdigit(c);c=getchar()) x=x*10+c-'0'; 8 return x; 9 } 10 long long v,n,m; 11 long long ans=-1; 12 long long sum[100005][2]; 13 priority_queue<long long> q; 14 struct node 15 { 16 long long a; 17 long long b; 18 }p[100005]; 19 inline bool cmp(node x,node y) 20 { 21 return x.a<y.a; 22 } 23 int main() 24 { 25 cin>>v>>n>>m; 26 for(int i=1;i<=n;i++) 27 { 28 scanf("%lld%lld",&p[i].a,&p[i].b); 29 } 30 sort(p+1,p+n+1,cmp); 31 if(m&1) 32 { 33 for(int i=1;i<=n;i++) 34 { 35 sum[i][0]=sum[i-1][0]+p[i].b; q.push(p[i].b); 36 if(q.size()>m/2) 37 { 38 sum[i][0]-=q.top(); 39 q.pop(); 40 } 41 } 42 while(!q.empty()) q.pop(); 43 for(int i=n;i>=1;i--) 44 { 45 sum[i][1]=sum[i+1][1]+p[i].b; q.push(p[i].b); 46 if(q.size()>m/2) 47 { 48 sum[i][1]-=q.top(); 49 q.pop(); 50 } 51 } 52 for(int i=m/2+1;i<=n-m/2;i++) 53 { 54 if(sum[i-1][0]+p[i].b+sum[i+1][1]<=v) 55 ans = max(ans, p[i].a); 56 } 57 printf("%lld\n",ans); 58 } 59 else 60 { 61 for(int i=1;i<=n;i++) 62 { 63 sum[i][0]=sum[i-1][0]+p[i].b; q.push(p[i].b); 64 if(q.size()>m/2-1) 65 { 66 sum[i][0]-=q.top(); 67 q.pop(); 68 } 69 } 70 while(!q.empty()) q.pop(); 71 for(int i=n;i>=1;i--) 72 { 73 sum[i][1]=sum[i+1][1]+p[i].b; q.push(p[i].b); 74 if(q.size()>m/2-1) 75 { 76 sum[i][1]-=q.top(); 77 q.pop(); 78 } 79 } 80 for(int i=m/2;i<=n-m/2;i++) //枚举左中位数 81 { 82 int le=i+1;int ri=n-m/2+1; 83 while(le<=ri) 84 { 85 int mid=le+ri>>1; 86 if(sum[i-1][0]+p[i].b+p[mid].b+sum[mid+1][1]<=v) 87 { 88 ans=max(ans,p[i].a+p[mid].a>>1); 89 le=mid+1; 90 } 91 else ri=mid-1; 92 } 93 } 94 printf("%lld\n",ans); 95 } 96 return 0; 97 }
小A的最短路
题目描述
小A这次来到一个景区去旅游,景区里面有N个景点,景点之间有N-1条路径。小A从当前的一个景点移动到下一个景点需要消耗一点的体力值。但是景区里面有两个景点比较特殊,它们之间是可以直接坐观光缆车通过,不需要消耗体力值。而小A不想走太多的路,所以他希望你能够告诉它,从当前的位置出发到他想要去的那个地方,他最少要消耗的体力值是多少。
输入描述:
第一行一个整数N代表景区的个数。
接下来N-1行每行两个整数u,v代表从位置u到v之间有一条路径可以互相到达。
接下来的一行两个整数U,V表示这两个城市之间可以直接坐缆车到达。
接下来一行一个整数Q,表示有Q次询问。
接下来的Q行每行两个整数x,y,代表小A的位置在x,而他想要去的地方是y。
输出描述:
对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力
示例1
输入
4 1 2 1 3 2 4 3 4 2 1 3 3 4
输出
1 0
备注:
1≤N≤3e5, 1≤Q≤1e6
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read() 4 { 5 int x=0;char c=getchar(); 6 for(;!isdigit(c);c=getchar()); 7 for(;isdigit(c);c=getchar()) x=x*10+c-'0'; 8 return x; 9 } 10 #define N 300005 11 int n,tot=0; 12 int nex[N<<1],head[N],to[N<<1]; 13 int size[N],d[N],fa[N],son[N],top[N]; 14 inline void add(int u,int v) 15 { 16 nex[++tot]=head[u]; 17 head[u]=tot; 18 to[tot]=v; 19 } 20 inline void dfs1(int u,int fat) 21 { 22 size[u]=1; 23 for(int i=head[u];i;i=nex[i]) 24 { 25 int v=to[i]; 26 if(v==fat) continue; 27 fa[v]=u; 28 d[v]=d[u]+1; 29 dfs1(v,u); 30 size[u]+=size[v]; 31 if(size[v]>size[son[u]]) son[u]=v; 32 } 33 } 34 inline void dfs2(int u,int tp) 35 { 36 top[u]=tp; 37 if(!son[u]) return; 38 dfs2(son[u],tp); 39 for(int i=head[u];i;i=nex[i]) 40 { 41 int v=to[i]; 42 if(v==fa[u]||v==son[u]) continue; 43 dfs2(v,v); 44 } 45 } 46 inline int LCA(int u,int v) 47 { 48 while(top[u]!=top[v]) 49 { 50 if(d[top[u]]<d[top[v]]) v=fa[top[v]]; 51 else u=fa[top[u]]; 52 } 53 if(d[u]>d[v]) return v; 54 else return u; 55 } 56 int main() 57 { 58 n=read(); 59 for(int i=1;i<n;i++) 60 { 61 int u=read(),v=read(); 62 add(u,v); 63 } 64 d[1]=1; 65 dfs1(1,-1); 66 dfs2(1,1); 67 int U=read(),V=read(); 68 int q=read(); 69 int lcaxy,lcaxu,lcaxv,lcayu,lcayv; 70 while(q--) 71 { 72 int ans=0; 73 int x=read(),y=read(); 74 lcaxy=LCA(x,y);lcaxu=LCA(x,U);lcaxv=LCA(x,V);lcayu=LCA(y,U);lcayv=LCA(y,V); 75 ans=min(d[x]-d[lcaxy]*2+d[y],(d[x]-d[lcaxu]*2+d[U])+(d[V]-d[lcayv]*2+d[y])); 76 ans=min(ans,(d[x]-d[lcaxv]*2+d[V])+(d[U]-d[lcayu]*2+d[y])); 77 //cout<<"topx="<<top[x]<<" dx="<<d[x]<<" topy="<<top[y]<<" dy="<<d[y]<<" top1="<<top[1]<<endl; 78 //cout<<"lca(x,y)="<<lcaxy<<endl; 79 printf("%d\n",ans); 80 } 81 return 0; 82 }

浙公网安备 33010602011771号