10.13多校联训

题意略。

T1 AT2672 [AGC018C] Coins

Sol
考场上面想的是六遍贪心做法,可惜写了300行使用替换功能的时候C++死了,心态爆炸就没再写。事后证明算法是正确的,但是码量上并不优秀。
这是我当时考试的解法:首先有个显然的贪心:每个人尽可能去取他有的最多的币种。但是会出现有的币种大家都多,而有的又缺的情况,所以需要调配多人的币种。接下来还可以证明的是对于三个币种的调配,一定是无环的,即如果有人从金币调到了银币,那就不会有银币调到金币,因为这样就不如他们都不调;三个的环同理。因此处于调配图的顶端的币种是不受其他币种的影响的,直接贪心,然后顺次贪心即可。但是无法确定顺序,所以枚举所有的六种贪心顺序取最值即可。由于码量巨大,所以其实并不可取。
题解的优质解法是这样的:假设每个人都取金币,然后题目就变成了从\(n\)个人中选\(Y\)个人取\(B_i-A_i\)个币,选\(Z\)个人取\(C_i-A_i\)个币,求最大值。把这\(n\)个人按照\(B_i-C_i\)从大到小排序,显然有改选银币的人全部在改选铜币的人之前,从前往后用优先队列维护前\(i\)个里面选\(Y\)个的最值,从后往前维护后\(i\)个里面选\(Z\)个的最值,最后枚举分界点求和的最值即可。
Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return f?x:-x;
}
const int maxn=100010;
int n,R,Y,G,ans,mx=-1e18;
priority_queue<int,vector<int>,greater<int> >qu1,qu2;
int maxb[maxn],maxa[maxn];
struct node
{
    int a,b;
    bool operator<(const node &x)const
    {
        return a-b>x.a-x.b;
    }
};
node dl[maxn];
signed main()
{
//    freopen("collection.in","r",stdin);
//    freopen("collection.out","w",stdout);
    R=read();Y=read();G=read();
    n=R+Y+G;
    for(int i=1;i<=n;i++)
    {
        int x=read(),y=read(),z=read();
        ans+=x;
        y-=x;z-=x;
        dl[i]=(node){y,z};
    }
    sort(dl+1,dl+n+1);
    if(Y)
    {
        for(int i=1;i<=Y;i++)
        {
            qu1.push(dl[i].a);
            maxb[i]=maxb[i-1]+dl[i].a;
        }
        for(int i=Y+1;i<=n;i++)
        {
            if(qu1.top()<dl[i].a)
            {
                maxb[i]=maxb[i-1]-qu1.top()+dl[i].a;
                qu1.pop();qu1.push(dl[i].a);
            }else maxb[i]=maxb[i-1];
        }
    }
    if(G)
    {
        for(int i=1;i<=G;i++)
        {
            qu2.push(dl[n-i+1].b);
            maxa[n-i+1]=maxa[n-i+2]+dl[n-i+1].b;
        }
        for(int i=G+1;i<=n;i++)
        {
            if(qu2.top()<dl[n-i+1].b)
            {
                maxa[n-i+1]=maxa[n-i+2]-qu2.top()+dl[n-i+1].b;
                qu2.pop();qu2.push(dl[n-i+1].b);
            }else maxa[n-i+1]=maxa[n-i+2];
        }
    }
    for(int i=Y;i<=n-G;i++)mx=max(mx,maxb[i]+maxa[i+1]);
    printf("%lld\n",ans+mx);
    return 0;
}

T2 AGC记不得了

Sol
真的不会。考场上因为有70的部分分都是修改操作很少的,所以直接合并相同操作的区间然后暴力。正解是按照从低位到高位建一颗\(0,1,2trie\)树,对于每次的0操作可以直接换子节点,1操作由于是从低到高修改,所以每次修改的复杂度不超过\(O(n)\)
Code
无。

T3 CF960H Santa's Gift

Sol
把柿子化一下就完了,树剖线段树维护修改即可(乱写的)。
Code
更莫得。

T4 CF????

总之就3500的题,爬了。

posted @ 2021-10-13 21:47  wwlvv  阅读(23)  评论(0)    收藏  举报