首页 > 其他分享 >Educational Codeforces Round 168 (Rated for Div. 2) 补题记录(A~E)

Educational Codeforces Round 168 (Rated for Div. 2) 补题记录(A~E)

时间:2024-07-31 10:42:25浏览次数:13  
标签:Educational Rated 格子 int mid long cin 补题 best

A

直接暴力枚举字符添加在哪里,以及添加的字符是什么即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
signed main(){
    int T;
    cin>>T;
    while(T--){
        string s;
        cin>>s;
        string ans;
        int mi=-1e18;
        for(int i=0;i<=s.size();++i){
            for(char ch='a';ch<='z';++ch){
                string aa;
                for(int j=0;j<i;++j)aa+=s[j];
                aa+=ch;
                for(int j=i;j<s.size();++j)aa+=s[j];
                int cost=2;
                for(int i=1;i<aa.size();++i)
                    if(aa[i]==aa[i-1])++cost;
                    else ++cost,++cost;
                if(mi<cost)
                    mi=cost,ans=aa;
            }
        }
        cout<<ans<<'\n';
    }
}

B

枚举每一个格子,现在需要计算当前的连通块数目:考虑使用动态维护图连通性的科技 考虑判断一个字符被染色之后对答案造成的贡献:如果这个格子位于角落那么显然不可以,否则这个格子和 \(3\) 个格子之间有边相连。若这个格子为这三个格子之间的割点,即删除这个格子之后和他相邻的三个格子会被分为三个互不连通的连通块,那么这个格子就对答案产生了 \(1\) 的贡献。

问题在于判定格子是否会产生贡献:若其周围三个格子都为空,且其左上(下)角和右上(下)角的格子都不空,那么让这个格子不空之后可以恰好产生三个连通块。因此直接判断即可。时间复杂度为 \(O(n)\)。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
char a[2][N];
signed main(){
    int T;
    cin>>T;
    while(T--){
        int n;cin>>n;
        for(int i=0;i<2;++i)scanf("%s",a[i]);
        int xx=0;for(int i=0;i<2;++i)for(int j=0;j<n;++j)
        if(a[i][j]=='.')++xx;if(xx==0)cout<<"0\n";
        else{
            int cnt=0;
            for(int i=0;i<2;++i)for(int j=0;j<n;++j)
            if(a[i][j]=='.'){
                if(i==0){
                    if((j!=0&&a[1][j-1]=='x'&&a[0][j-1]!='x')&&(j!=n-1&&a[1][j+1]=='x'&&a[0][j+1]!='x')&&a[1][j]!='x')++cnt;
                }else{
                    if((j!=0&&a[0][j-1]=='x'&&a[1][j-1]!='x')&&(j!=n-1&&a[0][j+1]=='x'&&a[1][j+1]!='x')&&a[0][j]!='x')++cnt;
                }
            }
            cout<<cnt<<'\n';
        }
    }
}

C

反悔贪心板子题。考虑尽量的让当前字符为右括号。如果到某一个前缀的时候右括号数量大于左括号数量,那么就贪心的让当前最后一个被变为右括号的括号变为左括号。这个变为右括号的括号集合用一个栈维护即可。时间复杂度为 \(O(n)\)。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
char s[N];
signed main(){
    int T;
    cin>>T;
    while(T--){
        int n;cin>>n;
        scanf("%s",s+1);
        int cnt=0;
        int c1=n/2,c2=n/2;
        for(int i=1;i<=n;++i)
            if(s[i]=='(')--c1;
            else if(s[i]==')')--c2;
        int pre=0;
        stack<int>laright;
        for(int i=1;i<=n;++i){
            if(s[i]=='_'){
                if(!pre)pre=1,s[i]='(',--c1;
                else if(!c2)++pre,s[i]='(',--c1;
                else --pre,--c2,s[i]=')',laright.emplace(i);
            }else if(s[i]=='(')++pre;
            else{
                --pre;
                if(pre<0){
                    pre+=2;
                    int t=laright.top();laright.pop();
                    s[t]='(';--c1,++c2;
                }
            }
        }
        stack<int>stk;
        for(int i=1;i<=n;++i)
            if(s[i]=='(')stk.push(i);
            else{
                cnt+=i-stk.top();
                stk.pop();
            }
        cout<<cnt<<'\n';
    }
}

D

不是,这题怎么才 \(1500\)??啊????(注:差点没切,wa 逆天点 #19)

看到最大值考虑二分然后将问题转化为判定问题。设现在判定答案 \(p\) 是否合法。

此时根节点值必须至少为 \(p\),且其他结点的值必须至少为 \(0\)。

现在强制令根节点的值不小于 \(p\),此时其他结点的值全部减去 \(p\)。

然后就是计算是否有一组方案满足其他结点的值全部大于等于 \(0\)。这是简单的。

把树从上往下遍历一遍。对于每一个非叶子结点 \(p\),记录其子树除她以外的结点集合为 \(SV\),则 \(SV\) 集合中每一个元素都需要为 \(p\) 结点做出贡献。记录贡献可以使用 dfs 序套线段树,也可以直接打一个标记然后 dfs 一遍。最后只需要判断虽有的叶子结点的值是否都非负即可。时间复杂度为 \(O(n\log n)\) 但是不知道为什么跑的十分的慢。

然后这个题难点是溢出问题,建议使用 Python

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
int a[N],n,jia[N];
vector<int>z[N];
__int128 b[N];
void dfs(int u,int fa,__int128 qian){
    b[u]-=qian;
    if(qian>1e12&&b[u]<0){
        b[u]=-233;
        return;
    }
    if(b[u]>=0){
        for(auto&v:z[u])
            if(v!=fa)dfs(v,u,qian);
    }else{
        int ok=1;
        for(auto&v:z[u])
            if(v!=fa)dfs(v,u,qian-b[u]),ok=0;
        if(!ok)
        b[u]=0;
    }
}
//判定根节点的值最后是否可以为p
bool check(int p){
    for(int i=1;i<=n;++i)b[i]=a[i],jia[i]=0;
    int jiax=max((__int128)(0),p-b[1]);
    b[1]+=jiax;
    for(int i=2;i<=n;++i)b[i]-=jiax;
    dfs(1,0,0);
    int ok=1;
    for(int i=1;i<=n;++i)if(b[i]<0){ok=0;break;}
    if(b[1]<p)ok=0;
    return ok;
}
signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int T;
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=1;i<=n;++i)cin>>a[i],z[i].clear();
        for(int i=2;i<=n;++i){
            int u=i,v;cin>>v;
            z[u].emplace_back(v),z[v].emplace_back(u);
        }
        int l=1,r=(int)(2e18)+2333,best=0;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid))best=mid,l=mid+1;
            else r=mid-1;
        }
        cout<<best<<'\n';
    }
}

E

使用伟大的数据结构。考虑对于每一个不同的 \(k\) 值,都扫描出答案:每一次二分出一段区间 \([l,r]\) 满足这一段区间内所有的位置 \(i\),这个人的等级都为 \(Lv\)。然后直接暴力二分扫描覆盖,判断答案是否成立即可。

更具体的说,二分一段区间 \([l,r]\) 可以每一次二分出对于当前的左端点 \(L\),最大的右端点 \(R\) 满足 \(L\sim R\) 一段区间中 \(\ge Lv\) 的数不超过 \(k\)。这个东西可以使用可持久化线段树来解决。看起来十分的慢。但是可以发现最外层的两次枚举并不是 \(O(n^2)\) 而是调和级数的。因此最终总的时间复杂度为 \(O(n\log^3n)\),大力卡常之后可以 \(3.8s\) 卡过。

#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
const int N=200100;
vector<pair<int,int>>scc[N];
struct qwq{
    int l,r,sum;
}z[N<<5];
int idx,a[N],rt[N],res[N];
int modify(int l,int r,int &rt,int p,int v){
    int pp=++idx;z[pp]=z[rt];
    if(l==r){
        z[pp].sum+=v;
        return pp;
    }
    int mid=l+r>>1;
    if(p<=mid)
        z[pp].l=modify(l,mid,z[rt].l,p,v);
    else
        z[pp].r=modify(mid+1,r,z[rt].r,p,v);
    z[pp].sum=z[z[pp].l].sum+z[z[pp].r].sum;
    return pp;
}
int query(int p,int l,int r,int k){
    if(l>=k)
        return z[p].sum;
    int mid=l+r>>1;
    if(k>mid)
        return query(z[p].r,mid+1,r,k);
    return query(z[p].l,l,mid,k)+z[z[p].r].sum;
}
signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n,q;cin>>n>>q;
    for(int i=1;i<=n;++i)cin>>a[i];
    for(int i=1;i<=q;++i){
        int v,x;cin>>v>>x;
        scc[x].emplace_back(v,i);
    }
    for(int i=1;i<=n;++i)
        rt[i]=modify(1,200001,rt[i-1],a[i],1);
    for(int i=1;i<=n;++i)
        sort(scc[i].begin(),scc[i].end());
    for(int i=1;i<=n;++i)
        if(scc[i].size()){
            int p=1,nowlevel=1;
            while(p<=scc[i].back().first){
                int l=p,r=scc[i].back().first,best=-1;
                //计算区间[l,r]中有多少个数>=now
                int presolve=query(rt[p-1],1,200001,nowlevel);
                while(l<=r){
                    int mid=l+r>>1;
                    if(query(rt[mid],1,200001,nowlevel)-presolve>=i)
                        best=mid,r=mid-1;
                    else
                        l=mid+1;
                }
                int lp;
                if(best==-1)
                    lp=n;
                else
                    lp=best;
                l=0,r=scc[i].size()-1,best=-1;
                while(l<=r){
                    int mid=l+r>>1;
                    if(scc[i][mid].first>=p)
                        best=mid,r=mid-1;
                    else
                        l=mid+1;
                }
                if(best!=-1){
                    for(int j=best;j<scc[i].size();++j)
                        if(scc[i][j].first>lp)break;
                        else if(a[scc[i][j].first]>=nowlevel)
                            res[scc[i][j].second]=1;
                }
                p=lp+1;
                ++nowlevel;
            }
        }
    for(int i=1;i<=q;++i)
        if(res[i])cout<<"YES\n";
        else cout<<"NO\n";
}

标签:Educational,Rated,格子,int,mid,long,cin,补题,best
From: https://www.cnblogs.com/yhbqwq/p/18334103

相关文章

  • Codeforces Round 958 (Div. 2)A(AC)BC(补题)
    这里写目录标题A思维题【AC】B贪心(+双指针)【补题】冗余代码(我的):大佬:双指针代码借鉴后代码C异或问题【补题】A思维题【AC】思路:每次分成k-1个1,1个其他#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;//constintN=2e5+10;v......
  • CF Div3 962补题 E-F
    CFDiv3962补题E-FE.Decode链接:Problem-E-Codeforces简要题意:给你一个长度为\(n\)的二进制字符串\(s\)。对于每一对整数\((l,r)\)\((1\leql\leqr\leqn)\)中,数出\((x,y)\)\((l\leqx\leqy\leqr)\)这样的整数对的个数。\((l\leqx\leqy\leq......
  • Pinely Round 4 (Div. 1 + Div. 2) 补题记录(A~F)
    打成乐子A容易证明下标为奇数的地方可以取到,下标为偶数的地方不可以取到。直接模拟时间复杂度为\(O(n)\)。#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1000100;inta[N];signedmain(){intT;scanf("%lld",&T);......
  • AtCoder Beginner Contest 364 补题记录(A~F)
    VP五十八分钟苏童流体。好耶A#defineGLIBCXX_DEBUG#include<iostream>#include<cstring>#include<cstdio>#defineintlonglongconstintN=500100;std::strings[N];signedmain(){intn,cnt=1;scanf("%lld",&n);f......
  • Codeforces Round 962 (Div. 3) 补题记录(A~G)
    这场Div.3难度高于平时。A#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=500100;inta[N];signedmain(){intT;scanf("%lld",&T);while(T--){intn;scanf("%lld",......
  • 平邑2024高算(补题)
    Day1risk题目描述解法考虑最后的集结,不妨考虑找出所有集结过程中可能经过的边,不难发现是一棵树,所以答案就是最小生成树。代码点击查看代码structnode{ intu,v,w;}e[3000001];intn,m;intfa[3000001];intfind(intx){ returnx==fa[x]?fa[x]:fa[x]=find(......
  • Codeforces Round 961 (Div. 2) 补题记录(A~D)
    上大分,赢!A考虑将每一条对角线上可以存放的砝码数量都记录一下,从大到小排序,然后直接暴力贪心选择。此时可以发现数量一定形如\(n,n-1,n-1,n-2,n-2,n-3,n-3,\ldots,1,1\)这样的形式。直接暴力减即可。时间复杂度为\(O(n)\)。#include<bits/stdc++.h>#defineintlonglong......
  • VMware Tanzu Kubernetes Grid Integrated Edition (TKGI) 1.19.1 - 运营商 Kubernete
    VMwareTanzuKubernetesGridIntegratedEdition(TKGI)1.19.1-运营商Kubernetes解决方案Kubernetes-basedcontainersolutionwithadvancednetworking,aprivatecontainerregistry,andlifecyclemanagement请访问原文链接:https://sysin.org/blog/vmware-tkgi/,......
  • 2024夏令营提高1模考0721模拟赛(提高1)补题报告
    2024夏令营提高1模考0721模拟赛(提高1)补题报告\[07121模拟赛(提高1)\\\补题报告\\\\2024年7月21日\\\by\\\唐一潇\]一、做题情况第一题比赛\(100/100\),赛后通过第二题比赛\(0/100\),赛后通过第三题比赛\(0/100\),赛后通过第四题比赛\(0/100\)......
  • AtCoder Beginner Contest 363 补题记录(A~F)
    难度:A<B<C<E≈F<<D做题顺序:A->B->C->F->E->D其实VP的时候perf还是有\(2000+\)的(虽然说D炸了),perf应该是\(2028\)左右Asignedmain(){intn;cin>>n;intcnt=0;do{++cnt;++......