Codeforces #398 (2) B 模拟 C dfs D 贪心,双指针 E 贪心,思维

Codeforces Round #398 (Div. 2)

B. The Queue

题意:护照处工件时间 ts 到 tf-1,已知有n个人各自会在 ti 时间到那排队,每人处理时间 t。Vasya想花最少时间排队,问他什么时间到那最好。

tags:骚到炸的题,很多坑,有时间再做一遍

//B
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e5+10;
const ll inf = 1e18;

ll ts, tf, t0, t1, t2, t[N], minn=inf, mi;
int n;
int main()
{
    scanf("%lld %lld %lld %d", &ts, &tf, &t0, &n);
    t1=ts;
    FF(i,1,n) scanf("%lld", &t[i]);
    FF(i,1,n) {
        t2=max(t[i], max(ts, t1));
        if(t1<t2) return 0*printf("%lld
", t1);
        t1=t2+t0;
        if(t2+t0-1>=tf) break;
        if(i!=n && t[i+1]-1>=t[i] && t2+t0-(t[i+1]-1)<minn && t2+t0*2-1<tf)
            minn=t2+t0-(t[i+1]-1), mi=t[i+1]-1;
    }
    if(t1+t0-1<tf) return 0*printf("%lld
", t1);
    if(t[1]-1>=0 && ts-(t[1]-1)<minn) printf("%lld
", t[1]-1);
    else printf("%lld
", mi);

    return 0;
}
View Code

C. Garland

题意:一个灯泡树,每个灯泡有一个温度 ti,要把这个灯泡树分成温度和相同的3部分,求在哪两条边断掉。

tags:dfs求出每个子树的Size,在dfs的过程中进行判断。因为温度可正可负,也有很多坑==

#include<bits/stdc++.h>
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e6+10;

int n, t[N], p, Size[N], ro, head[N], tot, sum, ans[3], cnt;
struct Edge{int to,next;}e[N];
void Addedge(int u,int v) { e[++tot].to=v, e[tot].next=head[u], head[u]=tot; }
void dfs(int u, int fa)
{
    Size[u]=t[u];
    for(int i=head[u]; i; i=e[i].next) {
        int v=e[i].to;
        if(v!=fa) {
            dfs(v, u);
            Size[u]+=Size[v];
        }
    }
    if(Size[u]==sum && u!=ro) {
        ans[++cnt]=u;
        Size[u]=0;
        if(cnt==2) printf("%d %d
", ans[1], ans[2]), exit(0);
    }
}
int main()
{
    scanf("%d", &n);
    FF(i,1,n) {
        scanf("%d %d", &p, &t[i]);
        Addedge(p, i), Addedge(i, p);
        if(p==0) ro=i;
        sum+=t[i];
    }
    if(sum%3) return 0*puts("-1");
    sum/=3;
    dfs(ro, 0);
    puts("-1");

    return 0;
}
View Code

 D. Cartons of milk

题意:冰箱里有n瓶牛奶,各有一个最后可饮用日期 fi;超市有m瓶牛奶,各有一个最后可饮用日期 si。Olya每天喝k瓶牛奶(如果没有k瓶就全部喝掉),Olya还可以到超市买牛奶。问Olya是否可以不浪费一瓶牛奶,如果可以,求Olya最多可以在超市买入多少瓶牛奶,并输出买入牛奶的编号。

tags:只要从后面往前贪心就好。对于冰箱里的一瓶牛奶 i:如 fi>k,则(fi-k)瓶要放在前面喝掉;如 fi<k,则最多可以买入(k-fi)瓶 i 日期后的牛奶。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 1e7+10;

int n, m, k, f[N], x, t1, t2, ans[N], cnt;
struct S{int id, v;}s[N];
bool cmp(S a, S b) { return a.v<b.v; }
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    FF(i,1,n) scanf("%d", &x), f[x]++;
    FF(i,1,m) scanf("%d", &s[i].v), s[i].id=i;
    t2=m;
    sort(s+1, s+1+m,cmp);
    F(i,N-1,0) {
        if(f[i]>k)
        {
            x=f[i]-k, t1=i-1;
            while(true) {
                if(t1<0) return 0*puts("-1");
                if(f[t1]<k) {
                    if(k-f[t1]>=x) f[t1]+=x, x=0;
                    else x-=(k-f[t1]), f[t1]=k;
                }
                if(x>0) t1--;
                else break;
            }
            f[i]=k;
        }
        else if(f[i]<k)
        {
            if(s[t2].v>=i) {
                x=k-f[i];
                while(true) {
                    if(t2<=0 || s[t2].v<i || x<=0) break;
                    ans[++cnt]=s[t2].id, s[t2].v=-1, x--, f[i]++;
                    t2--;
                }
            }
        }
    }
    printf("%d
", cnt);
    FF(i,1,cnt) printf("%d ", ans[i]);
    puts("");

    return 0;
}
View Code

 E. Change-free

题意:有两种货币:1元的硬币,100元的纸钞。Arseny有m个硬币,无穷多张纸钞。在未来的n天,他每天要花 ci元。收银员如果要找回 x元给Arseny,收银员的不开心值增加 x*w[i]。问Arseny每一天要怎么付款,使得最后收银员不开心值最小。

tags:有点考思维== 每一天付 ci元,关键就是 ci%100是要直接给硬币还是让收银员找。假设到了第 i 天,这 i 天先全部都直接给硬币,如果硬币数不够了,那说明前面 i 天就必须要有找回硬币的情况。到这里就是贪心了,找前面增加不开心值最少的一天,让这一天找回硬币。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e5+10;

ll n, m, c[N], w[N], ans, ci;
bool flag[N];
priority_queue<pair<ll, int > >Q;
int main()
{
    scanf("%lld %lld", &n, &m);
    FF(i,1,n) scanf("%lld", &c[i]);
    FF(i,1,n) scanf("%lld", &w[i]);
    FF(i,1,n) {
        ci=c[i]%100;
        if(ci==0) continue;
        Q.push({-(100-ci)*w[i], i});
        m-=ci;
        while(m<0) {
            int id=Q.top().second;
            ans+=(-Q.top().first);
            flag[id]=1;
            Q.pop();
            m+=100;
        }
    }
    printf("%lld
", ans);
    FF(i,1,n) printf("%lld %lld
", c[i]/100+flag[i], flag[i]?0LL:c[i]%100);

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/sbfhy/p/6414698.html