Codeforces Round 977 (Div. 2, based on COMPFEST 16 - Final Round) (A-E3)

写在前面

阳间比赛时间总出不太能做的阴间题

印尼的场,final round质量也还ok,算是学了两个经典trick吧

题目

A. Meaning Mean

排个降序后从小的开始合就好了,直觉上是哈夫曼树的合并方式,

但是只固定了第一个,后面的没有实时维护有序,也过了

代码

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,ll> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long ll;
const int N=55;
int t,n;
vector<int>a;
int main(){
    sci(t);
    while(t--){
        sci(n);
        a.resize(n);
        rep(i,1,n)sci(a[i-1]);
        sort(a.begin(),a.end(),greater<int>());
        while(SZ(a)>1){
            int x=a.back();a.pop_back();
            int y=a.back();a.pop_back();
            a.pb((x+y)/2);
        }
        pte(a[0]);
    }
    return 0;
}

B. Maximize Mex

这里是写了个O(nlogn)的,当然可以写成O(n)的,增序检查i,i用完了就留给i+x

代码

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,ll> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long ll;
const int N=55;
int t,n,x,v;
map<int,int>p,q;
int main(){
    sci(t);
    while(t--){
        sci(n);sci(x);
        q.clear();p.clear();
        rep(i,1,n){
            sci(v);
            q[v]++;
        }
        int mex=0;
        rep(i,0,n){
            if(q[i]){
                q[i]--;
                p[i%x]+=q[i];
                continue;
            }
            else if(p[i%x]){
                p[i%x]--;
                continue;
            }
            mex=i;
            break;
        }
        pte(mex);
    }
    return 0;
}

C1-C2. Adjust The Presentation(set维护前驱后继)

首先性质是,考虑b序列里的每个首次出现的数,需要和a序列里一一对应,

因为剩下的非首次位置,总能通过你的重新安排,使得它能在想要的时机出现

赛中写了个线段树,维护v当前在b序列的位置减v在a序列的位置,

然后需要让所有值都是0,感觉蠢完了

实际上之前也出过一个lca的题,维护相邻项即可,

EPIC Institute of Technology Round August 2024 D2. DFS Checker (Hard Version)(dfs序性质 lca)_epic institute of technology round august 2024 (di-CSDN博客

只需要关注对于每个a序列里的v,记它的前驱是pre[v],

v在b序列里的首次出现位置,

也需要满足在pre[v]在b序列里的首次位置的后面,

每次修改最多影响两个位置,对应影响其前驱和后继,

动态维护当前不合法的个数cnt即可

代码

#include<bits/stdc++.h>
using namespace std;
// #define DEBUG
#ifdef DEBUG
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define debug(...) [](auto...a){((cout<<a<<' '),...)<<endl;}(#__VA_ARGS__,":",__VA_ARGS__)
#define debugv(v) do{cout<<#v<<" : {";for(int izxc=0;izxc<v.size();++izxc){cout<<v[izxc];if(izxc+1!=v.size())cout <<", ";}cout<<"}"<<endl;}while(0)
#define debugmp(mp) do{cout<<#mp<<" : { ";for(auto p:mp){cout<<'['<<p.first<<" -> "<<p.second<<"] ";}cout<<"}"<<endl;}while(0)
#define debugset(s) do{cout<<#s<<" : {";for(auto x:s)cout<<x<<' ';cout<<"}"<<endl;}while(0)
#else
#define debug(...)
#define debugv(v)
#define debugmp(mp)
#define debugset(s)
#endif
typedef long long ll;
typedef pair<int, int> pii;

const int N = 2e5+5;
int a[N], pre[N], nxt[N], b[N];
set<int> s[N];



void solve() {
    int n, m, q; cin >> n >> m >> q;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) {
        if(i > 1) pre[a[i]] = a[i - 1];
        else pre[a[i]] = 0;
        if(i < n) nxt[a[i]] = a[i + 1];
        else nxt[a[i]] = 0;
    }
    for(int i = 1; i <= n; i++) {
        s[a[i]].clear();
        s[a[i]].insert(m + i);
    }
    for(int i = 1; i <= m; i++) {
        cin >> b[i];
        s[b[i]].insert(i);
    }
    int cnt = 0;
    for(int i = 2; i <= n; i++) {
        if(*s[a[i - 1]].begin() >= *s[a[i]].begin()) cnt++;
    }
    if(cnt == 0 ) cout << "YA" << endl;
    else cout << "TIDAK" << endl;
    while(q--) {
        int pos, t; cin >> pos >> t;
        if(b[pos] != t) {
            int x = b[pos];
            int tcnt = 0;
            if(pre[x] && *s[pre[x]].begin() >= *s[x].begin()) tcnt--;
            if(nxt[x] && *s[x].begin() >= *s[nxt[x]].begin()) tcnt--;
            s[x].erase(pos);
            if(pre[x] && *s[pre[x]].begin() >= *s[x].begin()) tcnt++;
            if(nxt[x] && *s[x].begin() >= *s[nxt[x]].begin()) tcnt++;
            cnt += tcnt;

            tcnt = 0;
            x = t;
            if(pre[x] && *s[pre[x]].begin() >= *s[x].begin()) tcnt--;
            if(nxt[x] && *s[x].begin() >= *s[nxt[x]].begin()) tcnt--;
            s[x].insert(pos);
            if(pre[x] && *s[pre[x]].begin() >= *s[x].begin()) tcnt++;
            if(nxt[x] && *s[x].begin() >= *s[nxt[x]].begin()) tcnt++;
            cnt += tcnt;

            b[pos] = t;
        }
        if(cnt == 0) cout << "YA" << endl;
        else cout << "TIDAK" << endl;
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int T; cin >> T;
    while(T--) solve();
    return 0;
}

D. Boss, Thirsty(dp优化)

单写了一篇博客,这里不再赘述了

Codeforces Round 977 (Div. 2, based on COMPFEST 16 - Final Round) D. Boss, Thirsty(前缀后缀max dp优化)-CSDN博客

代码

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=105,M=1e4+10;
const ll INF=1e15;
int t,n,m;
ll sol(){
    sci(n),sci(m);
    vector<vector<int>>a(n+1,vector<int>(m+1,0));
    vector<vector<ll>>f(n+1,vector<ll>(m+2,-INF));
    vector<vector<ll>>g(n+1,vector<ll>(m+2,-INF));
    vector<ll>pre(m+2,-INF),suf(m+2,-INF),sum(m+2,0);
    ll ans=-INF;
    rep(i,1,n){
        pre[0]=suf[m+1]=-INF;
        rep(j,1,m){
            sci(a[i][j]);
            sum[j]=sum[j-1]+a[i][j];
        }
        rep(j,1,m){
            pre[j]=max(pre[j-1],sum[m]-sum[j-1]);
        }
        per(j,m,1){
            suf[j]=max(suf[j+1],sum[j]);
        }
        auto premax=[&](int j){
            if(j<1)return 0ll;
            return pre[j]-(sum[m]-sum[j]);
        };
        auto sufmax=[&](int j){
            if(j>m)return 0ll;
            return suf[j]-sum[j-1];
        };
        if(i==1){
            rep(j,1,m){
                f[i][j]=sufmax(j);
                g[i][j]=premax(j);
            }
        }
        else{
            auto f1=[&](int k){
                return f[i-1][k]+sum[k]+max(0ll,sufmax(k+1));
            };
            auto f2=[&](int k){
                return f[i-1][k]-sum[k-2]+max(0ll,premax(k-2));
            };
            auto g1=[&](int k){
                return g[i-1][k]-sum[k-1]+max(0ll,premax(k-1));
            };
            auto g2=[&](int k){
                return g[i-1][k]+sum[k+1]+max(0ll,sufmax(k+2));
            };
            int p1=m,p2=m-1;
            per(j,m-1,1){
                if(f1(j+1)>f1(p1))p1=j+1;
                if(g2(j)>g2(p2))p2=j;
                f[i][j]=max(f1(p1),g2(p2))-sum[j-1];
            }
            int p3=1,p4=2;
            rep(j,2,m){
                if(g1(j-1)>g1(p3))p3=j-1;
                if(f2(j)>f2(p4))p4=j;
                g[i][j]=max(g1(p3),f2(p4))+sum[j];
            }
        }
        // rep(j,1,m){
        //     printf("i:%d j:%d f:%lld g:%lld\n",i,j,f[i][j],g[i][j]);
        // }
    }
    rep(j,1,m){
        ans=max(ans,f[n][j]);
        ans=max(ans,g[n][j]);
    }
    return ans;
}
int main(){
    sci(t);
    while(t--){
        ptlle(sol());
    }
    return 0;
}
/*
f[i][j]表示i行j列作为左端点必取的最大和
g[i][j]表示i行j列作为右端点必取的最大和
f[i][j]=max(k从j+1到m f[i-1][k]+sum[j,k]+sufmax[k+1:m]) sum[k]-sum[j-1] (f1)
g[i][j]=max(k从1到j-1 g[i-1][k]+sum[k,j]+premax[1:k-1]) sum[j]-sum[k-1] (g1)
f[i][j]=max(k从j到m-1 g[i-1][k]+sum[j,k+1]+sufmax[k+2:m]) sum[k+1]-sum[j-1] (g2)
g[i][j]=max(k从2到j f[i-1][k]+sum[k-1,j]+premax[1:k-2]) sum[j]-sum[k-2] (f2)
*/

E1-E3. Digital Village(树形背包 dp优化)

也单写了一篇博客

Codeforces Round 977 (Div. 2) E. Digital Village(树形背包 kruskal重构树 凸函数 闵可夫斯基和(min,+)差分优化)-CSDN博客

代码

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=2e5+10,M=4e5+10;
const ll INF=1e15;
int t,n,m,p,v,c,par[M],sz[M],W[M];
ll ans,dp[M];
vector<ll>f[M];
struct edge{
    int u,v,w;
}e[N];
int find(int x){
    return par[x]==x?x:par[x]=find(par[x]);
}
bool operator<(edge a,edge b){
    return a.w<b.w;
}
void dfs(int u,int fa){
    dp[u]=0;
    for(auto &v:f[u]){
        dfs(v,u);
        dp[u]=max(dp[u],dp[v]);
    }
    for(auto &v:f[u]){
        if(dp[u]==dp[v]){
            dp[v]=0;
            break;
        }
    }
    if(u<c){
        dp[u]+=1ll*sz[u]*(W[fa]-W[u]);
    }
}
int main(){
    sci(t);
    while(t--){
        sci(n),sci(m),sci(p);
        rep(i,1,n){
            par[i]=i;
            sz[i]=W[i]=0;
        }
        rep(i,1,p){
            sci(v);
            sz[v]=1;
        }
        rep(i,1,m){
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        }
        sort(e+1,e+m+1);
        c=n;
        rep(i,1,m){
            int u=find(e[i].u),v=find(e[i].v),w=e[i].w;
            if(u==v)continue;
            W[++c]=w;sz[c]=0;
            par[u]=par[v]=par[c]=c;
            f[c].pb(u);
            f[c].pb(v);
            sz[c]=sz[u]+sz[v];
        }
        dfs(c,0);
        ll ans=1ll*p*W[c];
        sort(dp+1,dp+c+1,greater<ll>());
        rep(i,1,n){
            ans-=dp[i];
            printf("%lld%c",ans," \n"[i==n]);
        }
        rep(i,1,c){
            f[i].clear();
        }
    }
    return 0;
}
/*
设kruskal重构树上点x有直连儿子y1、y2

假设y1内子树所有点都在y1处集结(已经通过y1及子树内的边联通),
如果有一个宽带在y1所在的连通块里,
就能阻止y1子树内所有点通过点x进入兄弟y2子树,
也就是x这条边权实际不需要连,也就是能省去y1->x增量的贡献

递归往下考虑,放的这一个宽带,
可以满足既在y1连通块里,也在y1直连儿子z1的连通块里,
这样就能省去z1->y1增量的贡献,取二者更大的那个显然更优,

递归到底实际是一个叶子,也就是原图上的点
所以放一个宽带最优影响的是一条权值和最大的重链
那么将kruskal重构树树链剖分后,按权值链降序贪心即可

由于实际转移是一个树形背包的形式,函数也都是凸函数,
所以闵可夫斯基和(min,+)卷积可以被拆成差分,即f(i+1)可以由f(i)得到
*/

抱歉,根据提供的引用内容,我无法理解你具体想要问什么问题。请提供更清晰明确的问题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【CodeforcesCodeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值