AtCoder Beginner Contest 355

ABC355 A - Who Ate the Cake?

题目传送门


代码(签到题)

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
int main(){
    int n=iut(),m=iut();
    if (n==m) printf("-1");
        else printf("%d",6-n-m);
    return 0;
}

ABC355 B - Piano 2

题目传送门


代码(签到题)

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,a[211],b[211];
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
int main(){
    n=iut(),m=iut();
    for (int i=1;i<=n;++i) a[i]=iut();
    for (int i=1;i<=m;++i) b[i]=iut();
    sort(a+1,a+1+n),sort(b+1,b+1+m);
    int I=1,J=1,flag=0;
    while (I<=n&&J<=m)
    if (a[I]<b[J]){
        if (flag) return !printf("Yes");
        flag=1,++I;
    }else ++J,flag=0;
    if (I<n) return !printf("Yes");
        else printf("No");
    return 0;
}

ABC355 C - Bingo 2

题目传送门


代码(签到题)

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2011;
int n,T,row[N],column[N],zhu,fu;
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
int main(){
    n=iut(),T=iut();
    for (int i=1;i<=T;++i){
        int t=iut(),x=(t-1)/n+1,y=t-(x-1)*n;
        ++row[x],++column[y];
        if (x==y) ++zhu;
        if (x+y==n+1) ++fu;
        if (row[x]==n||column[y]==n||zhu==n||fu==n)
            return !printf("%d",i);
    }
    return !printf("-1");
}

ABC355 D - Intersecting Intervals

题目传送门


分析

考虑容斥,用总数减去不相交的区间数,不相交的区间数可以用树状数组实现


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1000011;
long long ans;
int n,m,l[N],r[N],b[N],c[2][N];
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
void update(int x,int z){
    for (;x<=m;x+=-x&x) ++c[z][x];
}
int query(int x,int z){
    int ans=0;
    for (;x;x-=-x&x) ans+=c[z][x];
    return ans;
}
int main(){
    n=iut();
    for (int i=1;i<=n;++i){
        l[i]=iut(),r[i]=iut();
        b[++m]=l[i],b[++m]=r[i];
    }
    sort(b+1,b+1+m),m=unique(b+1,b+1+m)-b-1;
    ans=n*(n-1ll)/2;
    for (int i=1;i<=n;++i){
        l[i]=lower_bound(b+1,b+1+m,l[i])-b;
        r[i]=lower_bound(b+1,b+1+m,r[i])-b;
        ans-=query(l[i]-1,0)+i-1-query(r[i],1);
        update(r[i],0),update(l[i],1);
    }
    return !printf("%lld",ans);
}

ABC355 E - Guess the Sum

题目传送门


分析

实际上,连续和的求值可以变成两个前缀和相减的形式,而 (L,R) 区间最多只有 n2n 个,

要求询问次数最少,询问实际上只与端点有关,询问次数实际上是最短路,那么使用 BFS 找到最短路的路径,利用路径完成交互。


代码

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int N=300011; queue<int>q;
int pre[N],lg[N],n,L,R,ans,z;
void doit(int x){
    if (pre[x]==pre[L]) return;
    if (pre[x]<x) cout<<"? "<<lg[x-pre[x]]<<' '<<pre[x]/(x-pre[x])<<endl,cin>>z,ans=(ans+z)%100;
        else cout<<"? "<<lg[pre[x]-x]<<' '<<x/(pre[x]-x)<<endl,cin>>z,ans=(ans+100-z)%100;
    doit(pre[x]);
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>L>>R,++R,lg[0]=pre[0]=-1;
    for (int i=1;i<=(1<<n);++i) pre[i]=-1,lg[i]=lg[i>>1]+1;
    pre[L]=(1<<n)+1,q.push(L);
    while (!q.empty()){
        int x=q.front(); q.pop();
        if (x==R){
            doit(R);
            cout<<"! "<<ans<<endl;
            return 0;
        }
        if (!x){
            for (int z=1;z<pre[L];z<<=1)
                if (pre[z]==-1) q.push(z),pre[z]=x;
            continue;
        }
        for (int z=-x&x;z;z>>=1){
            if (x+z<pre[L]&&pre[x+z]==-1) q.push(x+z),pre[x+z]=x;
            if (pre[x-z]==-1) q.push(x-z),pre[x-z]=x;
        }
    }
    return 0;
}

ABC355 F - MST Query

题目传送门


分析

边权最多 10 种,一开始是一棵树,那么一开始的答案就是所有边权之和,

那么开 10 个并查集,第 i 个并查集中只装入边权大于等于 i 的边,

对于每个询问,将边丢入相应的并查集内,如果该边构成了新的生成树,说明原边被替换了,

假设原边的边权为 x,新边的边权为 y,那么在第 yx1 个并查集中均添加了新边,

减去 xy 的贡献,所以就是添加一个新边,就将答案减一。


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=200011;
int n,Q,f[10][N],ans;
int iut(){
    int ans=0; char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans;
}
void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
int getf(int j,int u){return f[j][u]==u?u:f[j][u]=getf(j,f[j][u]);}
int main(){
    n=iut(),Q=iut();
    for (int j=1;j<10;++j)
        for (int i=1;i<=n;++i) f[j][i]=i;
    for (int i=1;i<n;++i){
        int x=iut(),y=iut(),z=iut();
        ans+=z;
        for (int j=z;j<10;++j)
            f[j][getf(j,x)]=f[j][getf(j,y)];
    }
    for (int i=1;i<=Q;++i){
        int x=iut(),y=iut(),z=iut();
        for (int j=z;j<10;++j)
        if (getf(j,x)!=getf(j,y))
            f[j][getf(j,x)]=f[j][getf(j,y)],--ans;
        else break;
        print(ans),putchar(10);
    }
    return 0;
}

ABC355 G - Baseball

题目传送门


分析

乘上了 i=1nPi,不妨令第 0 个位置和第 n+1 个位置必选但在最小值时不可用。

那么题目就转换成了恰好选择 k 个点分成 k+1 段,对于相邻的选择点 x,y,使得 i=x+1y1min{ix,yi}×Pi 最小

dp[i][j] 表示前 i 个位置分成了 j 段的最小值,第二维由于式子满足四边形不等式,可利用决策单调性进行优化。

即使优化后仍是于事无补,考虑利用 WQS 二分斜率强加贡献,那么就变成了 O(nlognlogk),貌似斜率的二分上界要上到 long long


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=50011; int n,m,head,tail,K[N],a[N],f[N],q[N];
typedef long long lll; lll dp[N],s[N],S[N],ans;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
lll calc(int l,int r){
	if (l>r) return 0;
	if (l==1&&r==n) return 1e12;
	if (l==1) return (s[r]-s[l-1])*(r+1)-(S[r]-S[l-1]);
	if (r==n) return (S[r]-S[l-1])-(s[r]-s[l-1])*(l-1);
	int mid=(l+r)>>1;
	return (S[mid]-S[l-1])-(s[mid]-s[l-1])*(l-1)+(s[r]-s[mid])*(r+1)-(S[r]-S[mid]);
}
int ef(int X,int Y){
	int l=Y+1,r=n+2;
	while (l<r){
	    int mid=(l+r)>>1;
		if (dp[X]+calc(X+1,mid-1)>=dp[Y]+calc(Y+1,mid-1)) r=mid;
		    else l=mid+1;
	}
	return l;
}
void doit(lll mid){
	head=tail=0;
	for (int i=1;i<=n+1;++i){
		while (head<tail&&K[head]<=i) ++head;
		dp[i]=dp[q[head]]+calc(q[head]+1,i-1)+mid,f[i]=f[q[head]]+1;
		while (head<tail&&K[tail-1]>=ef(q[tail],i)) --tail;
		K[tail]=ef(q[tail],i),q[++tail]=i;
	}
}
int main(){
	n=iut(); m=iut()+1;
	for (int i=1;i<=n;++i) a[i]=iut();
	for (int i=1;i<=n;++i) s[i]=s[i-1]+a[i],S[i]=S[i-1]+1ll*a[i]*i;
	lll l=0,r=623623623617ll;
	while (l<r){
		lll mid=(l+r+1)>>1; doit(mid);
		if (f[n+1]>=m) ans=dp[n+1]-m*mid,l=mid;
		    else r=mid-1;
	}
	return !printf("%lld",ans);
}

posted @   lemondinosaur  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2020-10-07 #优化枚举#洛谷 2119 魔法阵
点击右上角即可分享
微信分享提示