2020牛客暑期多校训练营(第八场)
I Interesting Computer Game
并查集+树状数组离散化
要点一、由于题目中给出的对于a数组的数据范围在1~1e9,直接利用数组是不现实的,所以我们用数组a下标开数组,这个范围是1~1e5,开数组是能够接受的。
要点二、之前读取的数据存在重复,则需要对其进行去重操作。
要点三、查询连通块,如果是,输出连通块中的节点个数;否则节点数减一。
#include <bits/stdc++.h> #define T int t ;cin >> t;while(t--) using namespace std ; typedef long long ll; const int maxn = 2e5 + 10; ll vis[maxn],a[maxn],b[maxn],c[maxn],pre[maxn]; //vis数组表示的是当前的节点是否被访问过 //pre数组表示的是合并路径 inline ll find(ll x) { return (x==pre[x]) ? x:pre[x]=find(pre[x]); } inline void merge(ll u,ll v) { ll x=find(u),y=find(v); if(x==y) { vis[x]=1; return; } pre[x]=y;//表示x,y的祖宗合并,即两者为同一祖先 if(vis[x])vis[y]=1;//该节点表示已被访问 } int main() { ll total=0;//用于输出Case情况的个数 T { total++; ll n; ll tot=0;//tot表示存入数的个数 scanf("%lld",&n); for(ll i=1; i<=n; i++) { scanf("%lld%lld",&a[i],&b[i]); c[++tot]=a[i];//c数组用于存放每个数字,方便接下去排序和去重 c[++tot]=b[i]; } for(ll i=0; i<=maxn; i++)//初始化操作 { vis[i]=0; pre[i]=i; } sort(c+1,c+tot+1);//升序排序,便于接下来的去重 int cnt=unique(c+1,c+tot+1)-(c+1);//去重,方便编号 for(ll i=1; i<=n; i++) { a[i]=lower_bound(c+1,c+tot+1,a[i])-c; //从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字, //找到返回该数字的地址,不存在则返回end。 //通过返回的地址减去起始地址begin,得到找到数字在数组中的下标,下标即树的度数 b[i]=lower_bound(c+1,c+tot+1,b[i])-c; merge(a[i],b[i]);//用下标代替实际数字,防止数组存不下 } int ans=tot; for(ll i=1; i<=tot; i++) { if(pre[i]==i&&!vis[i])ans--;//根据《离散数学》相关知识,如果非连通块则ans减一 } cout<<"Case #"<<total<<": "<<ans<<endl; } }
K Kabaleo Lite
题意:第一天的人数就是最多人数,目标是为了获得利润最大化,期间不得中断,不管第一天是不是负利润的,则会酒店会继续运营下去,且必须全部卖出,如果之后某一天遇到负利润只取一份菜,接下去最多只能取一份菜,直到利润最大。
要点:前缀和,在每个价格读入后,均计算其前缀和
注意点:输出的数据类型要么采用__int128或者是long double,否则会Wa
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define N 50050 using namespace std; typedef long long ll; const ll maxn=1e5+5; template <typename _Tp> inline void read(_Tp&x); inline void print(__int128 x); template <typename _Tp> inline void read(_Tp&x) { char ch; bool flag=0; x=0; while(ch=getchar(),!isdigit(ch)) if(ch=='-')flag=1; while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); if(flag) x=-x; } inline void print(__int128 x) { if(x<0) { x=-x; putchar('-'); } if(x>9) print(x/10); putchar(x%10+'0'); } ll a[maxn],b[maxn]; int main() { ll t; scanf("%lld",&t); ll n; ll max_vis; for(ll i=1; i<=t; i++) { scanf("%lld",&n); scanf("%lld",&a[0]); for(ll j=1; j<n; j++) { scanf("%lld",&a[j]); a[j]=a[j-1]+a[j]; } scanf("%lld",&b[0]); for(ll j=1; j<n; j++) { scanf("%lld",&b[j]); b[j]=min(b[j],b[j-1]); } long double max1=a[0]; long double max_profit=0; b[n]=0; a[n]=a[n-1]; for(ll j=1; j<=n; j++) { max_profit+=max1*(b[j-1]-b[j]); if(max1<a[j]) max1=a[j]; } printf("Case #%lld: %lld %.0Lf\n",i,b[0],max_profit); } }
作者:Drophair
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。