• Codeforces Round #481 (Div. 3)


    我实在是因为无聊至极来写Div3题解

    感觉我主要的作用也就是翻译一下题目

    第一次线上打CF的比赛,手速很重要。

    这次由于所有题目都是1A,所以罚时还可以。

    下面开始讲题

    A.Remove Duplicates

    题目大意:给你一个序列,让你对这个序列中重复的数进行去重。要求相对顺序不变并且有限保留右边的。

    首先这道题O(n)扫一遍+hash是可以的,但是这数据范围。。。

    开桶即可。

    CODE

    #include<cstdio>
    const int N=55;
    int a[N],n,ans[N],tot;
    bool h[1005];
    int main()
    {
    	register int i;
    	for (scanf("%d",&n),i=1;i<=n;++i)
    	scanf("%d",&a[i]);
    	for (i=n;i>=1;--i)
    	if (!h[a[i]]) h[a[i]]=1,ans[++tot]=a[i];
    	for (printf("%d
    ",tot),i=tot;i>=1;--i)
    	printf("%d ",ans[i]);
    	return 0;
    }
    

    B.File Name

    题目大意:给你一个字符串,问你至少要删去几个字符才能使字符串中没有三个连续的'x'

    直接扫一遍即可,每次看一下连续的x个数是多少。设统计出的个数为t,那么ans+=t-2(t>=3)

    CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=105;
    char s[N],tot,ans;
    int n;
    int main()
    {
    	register int i;
    	scanf("%d",&n); scanf("%s",s+1);
    	for (i=1;i<=n;++i)
    	if (s[i]=='x') ++tot; else
    	{
    		if (tot>=3) ans+=tot-2; tot=0;
    	}
    	if (tot>=3) ans+=tot-2;
    	printf("%d",ans);
    	return 0;
    }
    

    C. Letters

    题目大意:给你n段数的中每一段数的长度。然后对于m个询问,给出这个数在第几段中的第几个。

    题目很抽象?那我们根据第一个样例理解一下。

    首先我们看1,就是第一段的第一个。又对于12,他是第二段的第二个(因为第一段长度为10)

    然后我们可以先前缀和+二分弄出这一个数属于第几段,然后减一下即可。

    但其实根本不需要二分,因为题目中说了所有的数严格递增但我没看见

    不过二分也可以艹过去(虚什么)。

    CODE

    #include<cstdio>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    LL n,m,x,sum[N];
    inline LL find(LL x)
    {
    	LL l=0,r=n,res;
    	while (l<=r)
    	{
    		LL mid=(l+r)/2;
    		if (sum[mid]<=x) res=mid,l=mid+1; else r=mid-1;
    	}
    	return res;
    }
    int main()
    {
    	register LL i;
    	scanf("%I64d%I64d",&n,&m);
    	for (i=1;i<=n;++i)
    	scanf("%I64d",&x),sum[i]=sum[i-1]+x;
    	for (i=1;i<=m;++i)
    	{
    		scanf("%I64d",&x); LL k=find(x);
    		if (sum[k]==x) printf("%I64d %I64d
    ",k,sum[k]-sum[k-1]); else printf("%I64d %I64d
    ",k+1,x-sum[k]);
    	}
    	return 0;
    }
    

    D. Almost Arithmetic Progression

    题目大意:给你一串数,问你是否可以将每一个数通过不变||加1||减1三种操作的一种变成等差数列,若可以输出最少操作次数(不变不算次数),否则输出-1

    等差数列的题目都有一个共同的尿性方法:确定了前两项,其他的值就确定了

    所以我们枚举前两项的情况,然后对于所有有解的情况取最小值即可

    CODE

    #include<cstdio>
    using namespace std;
    const int N=100005;
    int a[N],n,ans=N;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline int abs(int x)
    {
    	return x>0?x:-x;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    inline int check(int p,int q)
    {
    	int x=a[1]+p,y=a[2]+q,d=y-x,last=y,tot=0;
    	for (register int i=3;i<=n;++i)
    	if (abs(a[i]-last-d)==1) ++tot,last+=d; else
    	{ if (abs(a[i]-last-d)!=0) return -1; else last+=d; }
    	return tot;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i;
    	for (read(n),i=1;i<=n;++i)
    	read(a[i]);
    	int k=check(0,0); if (k!=-1) ans=min(ans,k);
    	k=check(1,0); if (k!=-1) ans=min(ans,k+1);
    	k=check(-1,0); if (k!=-1) ans=min(ans,k+1);
    	k=check(0,1); if (k!=-1) ans=min(ans,k+1);
    	k=check(0,-1); if (k!=-1) ans=min(ans,k+1);
    	k=check(1,1); if (k!=-1) ans=min(ans,k+2);
    	k=check(-1,-1); if (k!=-1) ans=min(ans,k+2);
    	k=check(-1,1); if (k!=-1) ans=min(ans,k+2);
    	k=check(1,-1); if (k!=-1) ans=min(ans,k+2);
    	if (ans!=N) printf("%d",ans); else puts("-1");
    	return 0;
    }
    

    E. Bus Video System

    题目大意:给你一个公交车的上下车情况,正数表示上车,当然负数就是下车。还给出了车的最大容量,车上的人数任何时候都不得超过最大容量。让你求车上最开始时车上的人数的可能情况

    首先我们应该主要到这个人数是个区间,所以我们统计出车上可能人数的最少值l和最大值r,最后输出r-l+1即可。特别地,若r<l则输出0

    对于合法性只需要满足两个关键条件:

    1. 车上的人数任何时候都不得超过最大容量

    2. 车上的人数任何时候都不得为负数

    然后min,max转移l,r即可

    具体看CODE

    #include<cstdio>
    using namespace std;
    const int N=1005;
    int n,m,x,sum[N],l,r;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc(); int flag=1;
    	while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=tc(); }
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    	x*=flag;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i; read(n),read(m);
    	for (r=m,l=0,i=1;i<=n;++i)
    	{
    		read(x); sum[i]=sum[i-1]+x;
    		if (sum[i]>=0) r=min(r,m-sum[i]); 
    		if (sum[i]<=0) l=max(l,-sum[i]);
    	}
    	if (l>r) puts("0"); else printf("%d",r-l+1);
    	return 0;
    }
    

    F. Mentors

    这道题还是卡了一下的

    题目大意:给你一个序列和一些关系。让你求对于每一个数,在序列中有多少数严格小于这个数并且和这个数没有关系。

    首先我们sort一遍,求出对于每一个数有多少数比他小。

    然后对于读入的关系,我们将较大的那个数的个数减1即可

    CODE

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=2e5+5;
    struct data
    {
    	int x,num;
    }a[N];
    int n,m,r[N],s[N],x,y;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc(); 
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline bool comp(data a,data b)
    {
    	if (a.x<b.x) return 1;
    	if (a.x>b.x) return 0;
    	if (a.num<b.num) return 1;
    	return 0;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i;
    	read(n); read(m);
    	for (i=1;i<=n;++i)
    	read(a[i].x),a[i].num=i;
    	sort(a+1,a+n+1,comp);
    	for (i=1;i<=n;++i)
    	r[a[i].num]=i;
    	for (i=1;i<=n;++i)
    	if (a[i].x==a[i-1].x) s[i]=s[i-1]; else s[i]=i;
    	while (m--)
    	{
    		read(x); read(y);
    		if (a[r[x]].x>a[r[y]].x) --s[r[x]];
    		if (a[r[y]].x>a[r[x]].x) --s[r[y]];
    	}
    	for (i=1;i<=n;++i)
    	printf("%d ",s[r[i]]-1);
    	return 0;
    }
    

    G. Petya's Exams

    题目大意:一个人在n天内要参加m场考试。每一场考试都有一个可以开始复习的时间和考试时间,以及需要复习的时间。对于一场考试,如果没有复习满相应的天数就输出-1。

    这个人每天可以从三项事情中选择一项去做:

    1. 休息,用0来表示

    2. 考试,进行每一场考试(考试当天无法复习),用m+1表示

    3. 复习,用i表示复习第i次考试的内容

    让你求一种可以的安排方式,使得它通过所有的考试。输出每一天做的事情。

    还是很简单的,一个小贪心,对于所有考试,肯定优先复习先开始的。除非有考试或者没有东西复习。

    我们sort一遍然后枚举所有时间点即可

    CODE

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=105;
    struct data
    {
    	int s,t,d,id;
    }a[N];
    int ans[N],t[N],num[N],n,m;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline bool comp(data a,data b)
    {
    	return a.t<b.t;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i,j; read(n); read(m);
    	for (i=1;i<=m;++i)
    	read(a[i].s),read(a[i].t),read(a[i].d),a[i].id=i;
    	sort(a+1,a+m+1,comp);
    	for (i=1;i<=m;++i)
    	num[a[i].t]=i;
    	for (i=1;i<=n;++i)
    	{
    		if (num[i]) 
    		{
    			if (t[num[i]]==a[num[i]].d) { ans[i]=m+1; continue; } else { puts("-1"); return 0; }
    		}
    		for (j=1;j<=m;++j)
    		if (t[j]!=a[j].d&&i>=a[j].s) { ans[i]=a[j].id; ++t[j]; break; }  
    	}
    	for (i=1;i<=n;++i)
    	printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    美女检测器
    汉字动画程序的原理
    值类型不是值类型(ValueType is NOT a Value Type):闲谈.Net类型
    PowerShell 简介
    Visual Studio 2012 RC 发布
    使用 MvcMiniProfiler 监控EF 4.1 with MySQL Provider
    NuGet安装及简单使用
    发布自己的NuGet程序
    Qizmt 单机及分布式部署注意事项
    JDynamic :支持Json反序列化为Dynamic对象
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9094468.html
Copyright © 2020-2023  润新知