首页 > 其他分享 >AGC011 题解

AGC011 题解

时间:2023-03-16 17:35:04浏览次数:51  
标签:cnt AGC011 int 题解 sum edge ans include

敬告各位:大佬魔怔那叫乐呵,如果实力不够还魔怔那叫小丑。

这其实和洛谷灌水区是一个道理,现在灌水区不是流汗就是流汗。虽然有几个真正提问的。

[AGC011A] Airport Bus

普及题。排序贪心扫一遍。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,c,k,ans,a[100010];
int main(){
    scanf("%d%d%d",&n,&c,&k);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    int cnt=0,t=0;
    for(int i=1;i<=n;i++){
        if(cnt>=c||a[i]>t)t=a[i]+k,cnt=1,ans++;
        else cnt++;
    }
    printf("%d\n",ans);
    return 0;
}

[AGC011B] Colorful Creatures

普及题。贪心合并。开 long long。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
int n,ans,a[100010];
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        if(a[i+1]<=2*a[i])ans++;
        else ans=0;
        a[i+1]+=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}

[AGC011C] Squared Graph

这玩意我真不会。感觉 D 和 E 要比这题简单很多。

考虑两对点 \((a,b),(c,d)\) 在同一个连通块内的条件: \(a\rightarrow c,b\rightarrow d\) 路径的奇偶性相同。

那么可以分每个连通块分别考虑。如果连通块有奇环,那么连通块内任意两个点都有一条长度为奇的路径和一条长度为偶的路径,即自己有 \(1\) 的贡献。如果没有,那么奇偶分开,自己有 \(2\) 的贡献。特殊处理所有单独的点,自己有 \(1\) 的贡献。

考虑连通块间的贡献。顺序考虑有奇环/无奇环/单点。有奇环的之间会产生 \(2\) 的贡献。无奇环的之间有 \(4\) 的贡献,会和有奇环的产生 \(2\) 的贡献。单点会和剩下的所有节点产生 \(2\) 的贡献。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,a,b,c,col[100010];
struct node{
    int v,next;
}edge[400010];
int t,head[100010];
void add(int u,int v){
    edge[++t].v=v;edge[t].next=head[u];head[u]=t;
}
bool dfs(int x,int c){
    col[x]=c;
    bool jud=true;
    for(int i=head[x];i;i=edge[i].next){
        if(col[edge[i].v]){
            if(col[edge[i].v]==col[x])jud=false;
        }
        else jud&=dfs(edge[i].v,3-c);
    }
    return jud;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v;scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++){
        if(col[i])continue;
        if(!head[i])c++;
        else{
            if(dfs(i,1))b++;
            else a++;
        }
    }
    long long ans=0;
    int cnt=0;
    for(int i=1;i<=a;i++)ans+=2*cnt+1,cnt++;
    for(int i=1;i<=b;i++)ans+=2*cnt+2,cnt+=2;
    cnt=n-c;
    for(int i=1;i<=c;i++)ans+=2*cnt+1,cnt++;
    printf("%lld\n",ans);
    return 0;
}

[AGC011D] Half Reflector

手模样例题。

手模样例可以得到一次操作的变化规律:如果开头是 A,那改成 B。如果开头是 B,那么把开头去掉,后边的串 AB 翻转,最后加个 A。

接着模可以得到另一个结论:所有的最后都会变成 BABABABA\(\cdots\) 的样子。如果串长是偶数那就固定了。如果是奇数那第一个会在 AB 之间来回变。显然最多需要 \(2n\) 次变成这样。

那直接模拟复杂度就是 \(O(n)\) 的了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,k,a[800010];
char s[200010];
int main(){
    scanf("%d%d%s",&n,&k,s+1);
    for(int i=1;i<=n;i++)a[i]=s[i]-'A';
    int od=0,l=1;
    for(int i=1;i<=min(k,n<<1);i++){
        if((a[l]^od)==0)a[l]^=1;
        else od^=1,l++,a[l+n-1]=od;
    }
    k-=min(k,n<<1);
    if((k&1)&&(n&1))a[l]^=1;
    for(int i=l;i<=l+n-1;i++)putchar((a[i]^od)+'A');
    puts("");
    return 0;
}

[AGC011E] Increasing Numbers

小清新数学题。也不是很数学。

首先每个递增的数都可以变成形如 \(\sum_{i=1}^9\dfrac{10^{a_{i}}-1}9\) 的形式。然后设答案是 \(cnt\),有

\[n=\sum_{i=1}^{cnt}\sum_{j=1}^9\dfrac{10^{a_{i,j}}-1}9 \]

\[9n+9cnt=\sum_{i=1}^{cnt}\sum_{j=1}^910^{a_{i,j}} \]

看看右边是什么东西。如果右边 \(a_{i,j}\) 互不相同,那么显然数位和是 \(9cnt\)。如果有重复,一次进位就是 \(-9\)。也就是说只要 \(9n+9cnt\) 的数位和 \(\le 9cnt\) 就行了。\(cnt\) 的上界显然是 \(n\)。高精暴力算,复杂度 \(O(n)\)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
struct bignum{
    int a[1000010],sum;
    bignum(){a[0]=1;}
    void plus(int n){
        int x=n;
        for(int i=1;x;i++){
            sum-=a[i];
            a[i]+=x;
            x=a[i]/10;a[i]%=10;
            sum+=a[i];
            if(a[0]<i)a[0]=i;
        }
    }
    void mul(int n){
        int x=0;
        for(int i=1;i<=a[0]||x;i++){
            a[i]=a[i]*n+x;
            x=a[i]/10;a[i]%=10;
            if(a[0]<i)a[i]=i;
        }
    }
}a;
int b;
char s[500010];
int main(){
    scanf("%s",s+1);n=strlen(s+1);
    for(int i=n;i>=1;i--)a.a[n-i+1]=s[i]-'0';
    a.a[0]=n;
    a.mul(9);
    for(int i=1;i<=a.a[0];i++)a.sum+=a.a[i];
    for(int k=1;k<=n;k++){
        a.plus(9);b+=9;
        if(a.sum<=b){
            printf("%d\n",k);
            break;
        }
    }
    return 0;
}

[AGC011F] Train Service Planning

神仙题。这个银牌不亏。

首先题意需要读明白。我语文和英语都不是很好,翻了翻题解才知道题面在说什么。

首先显然时间可以 \(\bmod k\) 意义下搞。然后只要搞 \(0-n\) 和 \(n-0\) 两辆车。那我们设两个数组 \(p,q\),分别为第一辆和第二辆车在每个站停的时间,并做前缀和 \(suma,sump,sumq\)。

那么我们的条件就变成了若干区间不交。即:

\[(sump_{i-1}+suma_{i-1},sump_{i-1}+suma_i)\cap(-sumq_{i-1}-suma_i,-sumq_{i-1}-suma_{i-1})=\emptyset \]

这个负号可能有点奇怪。其实由于一整轮的时间是 \(k\) 的倍数,那么 \(\bmod k\) 意义下就没了,只剩下减掉的前缀和。

解一车方程,得到

\[sump_{i-1}+sumq_{i-1}\in[-2suma_{i-1},-2suma_i] \]

然后 \(sump,sumq\) 递增,因此问题就变成了:有若干区间 \([l_i,r_i]\),初始有一个数 \(x\),初值任意,每次加一个数使得落在区间内,求最少加多少。

考虑解决这个问题。若起点确定,下一次显然走到左端点最优。那么先预处理每个起点出发后一直走左端点的最小距离,这个可以整棵线段树,每次查区间 \([l_i,r_i]\) 的时候查到后面第一个和这个区间无交的区间 \([l_j,r_j]\),用 \(dp_j+dis(l_i,l_j)\) 更新 \(dp_i\),然后覆盖区间。

最后枚举所有的 \(l_i,r_i\) 为起点统计答案就可以了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
int n,mod,cnt,a[200010],b[200010],sum[200010],l[200010],r[200010],lsh[400010];
int tree[800010],dp[200010];
void pushdown(int rt){
    if(tree[rt]){
        tree[lson]=tree[rson]=tree[rt];tree[rt]=0;
    }
}
void update(int rt,int L,int R,int l,int r,int val){
    if(l>r)return;
    if(l<=L&&R<=r){
        tree[rt]=val;return;
    }
    pushdown(rt);
    int mid=(L+R)>>1;
    if(l<=mid)update(lson,L,mid,l,r,val);
    if(mid<r)update(rson,mid+1,R,l,r,val);
}
int query(int rt,int l,int r,int pos){
    if(l==r)return tree[rt];
    pushdown(rt);
    int mid=(l+r)>>1;
    if(pos<=mid)return query(lson,l,mid,pos);
    else return query(rson,mid+1,r,pos);
}
int get(int pos){
    int x=query(1,1,cnt,pos);
    if(!x)return 0;
    return dp[x]+(lsh[l[x]]-lsh[pos]+mod)%mod;
}
signed main(){
    scanf("%lld%lld",&n,&mod);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&a[i],&b[i]);
        sum[i]=sum[i-1]+a[i];
        if(b[i]==1&&2*a[i]>mod){
            puts("-1");return 0;
        }
    }
    for(int i=1;i<=n;i++){
        if(b[i]==1){
            l[i]=(mod-2ll*sum[i-1]%mod)%mod;
            r[i]=(mod-2ll*sum[i]%mod)%mod;
        }
        else l[i]=0,r[i]=mod-1;
        lsh[++cnt]=l[i];lsh[++cnt]=r[i];
    }
    sort(lsh+1,lsh+cnt+1);
    cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
    for(int i=n;i>=1;i--){
        l[i]=lower_bound(lsh+1,lsh+cnt+1,l[i])-lsh;
        r[i]=lower_bound(lsh+1,lsh+cnt+1,r[i])-lsh;
        dp[i]=get(l[i]);
        if(l[i]>r[i])update(1,1,cnt,r[i]+1,l[i]-1,i);
        else update(1,1,cnt,1,l[i]-1,i),update(1,1,cnt,r[i]+1,cnt,i);
    }
    int ans=dp[1];
    for(int i=cnt;i>=1;i--)ans=min(ans,get(i));
    printf("%lld\n",ans+2*sum[n]);
    return 0;
}

标签:cnt,AGC011,int,题解,sum,edge,ans,include
From: https://www.cnblogs.com/gtm1514/p/17223505.html

相关文章

  • 「BZOJ3864」Hero meet devil 题解
    简要题意给你一个只由\(AGCT\)组成的字符串\(S\),对于每个\(0\leqi\leq|S|\),问有多少个只由\(AGCT\)组成的长度为\(m\)的字符串\(T\),使得\(LCS(S,T)=i\)SOLU......
  • [HNOI2015]落忆枫音 题解
    题目背景...题目描述不妨假设枫叶上有n个穴位,穴位的编号为1~n。有若干条有向的脉络连接着这些穴位。穴位和脉络组成一个有向无环图——称之为脉络图(例如图1),穴位的......
  • 题解 GDKOI2023 普及 D2T4
    口胡。problem一个图,边带权,有\(k\leq50\)个关键边,对于\(0\leqi\leqk\)求出恰好含有\(i\)条关键边的最小生成树的权值和。\(n\leq10000,m\leq10^6,k\leq50\)......
  • NOI 2008 志愿者招募 题解 (神奇费用流)
    洛谷题目链接思路很清奇的网络流题这种第i天需要至少\(a_i\)人的限制,按常规思路容易想到在i号点和i+1号点之间连一条容量为\(a_i\)的边,并强制流满。但是如果雇佣了一个人......
  • ARC153B Grid Rotations 题解
    B-GridRotations(atcoder.jp)SOLUTION我表示大为不理解。。。。这个简单......
  • 選択問題の正答はすべて同じ選択肢で… 题解
    题目传送门由于数据问题,我们可以使用C++STL里的map存储企鹅君选择的答案以及次数。先定义一个map,用来储存答题情况。接着将企鹅君的答案存入map,顺便求出最大值。m......
  • 洛谷-P9147 题解
    正文最坏时间复杂度:\(\mathcal{O}(n)\)真不愧是签到题,差点没签上。。。我相信题意各位肯定很理解了,非常简单,但如何解决就是个问题。首先考虑朴素解法,建立一个求最长连......
  • 【题解】P6667 [清华集训2016] 如何优雅地求和
    orzfjy666orzfjy666orzfjy666神·fjy666·拉普拉斯·爱因斯坦大帝于5min内爆切了此题,膜拜!思路斯特林数。注意到\(f(k)\)是多项式而式子中含有组合数,于......
  • 公众号前端访问后台500 疑难问题解决
     后台日志联调,发现前端根本无法进入后台方法中去经过仔细对比发现referrer请求过长在主设置页面增加<metaname="referrer"content="origin">配置问题解决 ......
  • 阿里一面:15道网络安全真题解析,你能答对几道?
    前言网络安全是一个广阔的领域,面试过程中可能会提出各种各样的问题。招聘人员主要关注技术方面以及工具和技术知识,以确保框架安全。 以下是在网络安全领域寻求工作时可能......