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);
    }
}

 

posted @ 2020-08-06 21:03  Drophair  阅读(177)  评论(0编辑  收藏  举报