zoukankan      html  css  js  c++  java
  • [2019.3.8]codeforces1138 Codeforces Round #545 (Div. 2)

    概况

    排名:47/3403

    过题数:4

    Rating:(color{green}{+118})((color{purple}{1910}))

    (上(color{purple}{紫})啦!)

    题目

    A. Sushi for Two

    AC时间:3min,496分

    题解:

    每次记录相同的连续长度,和上一个长度取个min,更新答案就好了。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[100010],ans,tot,lst;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scanf("%d",&a[i]),a[i]!=a[i-1]?ans=max(ans,min(tot,lst)),lst=tot,tot=0:0,++tot;
    	ans=max(ans,min(lst,tot));
    	printf("%d",ans*2);
    	return 0;
    }
    

    B. Circus

    AC时间:33min,845分(-1)

    B题想了半小时。。。我以为我完了。。。

    题解:

    (c_i=1,a_i=0)为第一种,数量为(tot_1);(c_i=1,a_i=1)为第二种,数量为(tot_2);(c_i=0,a_i=1)为第三种,数量为(tot_3);(c_i=0,a_i=0)为第四种,数量为(tot_4)

    我们枚举第一场中第一种,第二种的数量,发现剩下两种的(c_i=0),所以第一场有几个会的就确定了,那么第二场有几个会的也确定了,由于剩下的第二种人必然会在第二场,也就是必然会对第二场会的人数做出贡献,所以第二场中有几个第三种人也确定了,那么第一场有几个第三种人也确定了,又因为第一场中必然有(frac{n}{2})个人,那么第一场中第四种人的数量也随之确定。

    然后判断方案合法性即可。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    int n,c[5010],a[5010],tot1,tot2,tot3,tt1,tt2,tt3,tt4,t1,t2;
    void scan(int &x){
    	x=getchar();
    	while(!isdigit(x))x=getchar();
    	x-='0';
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scan(c[i]);
    	for(int i=1;i<=n;++i)scan(a[i]),c[i]?(a[i]?++tot2:++tot1):tot3+=a[i];
    	for(int i=0;i<=tot1;++i){
    		for(int j=0;j<=tot2&&i+j<=n/2;++j){
    			t1=i+j,t2=tot2-j;
    			if(t1<t2)continue;
    			tt1=i,tt2=j,tt3=tot3-(t1-t2),tt4=n/2-tt1-tt2-tt3;
    			if(tt1>tot1||tt2>tot2||tt3>tot3||tt4>n-tot1-tot2-tot3)continue;
    			if(tt3>=0&&tt4>=0)goto ANS;
    		}
    	}
    	puts("-1");
    	return 0;
    	ANS:
    	for(int i=1;i<=n;++i){
    		if(c[i]&&!a[i]&&tt1)printf("%d ",i),--tt1;
    		if(c[i]&&a[i]&&tt2)printf("%d ",i),--tt2;
    		if(!c[i]&&a[i]&&tt3)printf("%d ",i),--tt3;
    		if(!c[i]&&!a[i]&&tt4)printf("%d ",i),--tt4;
    	}
    	return 0;
    }
    

    C. Skyscrapers

    AC时间:49min,1476分

    题解:

    比B水得多。

    记第(i)行第(j)列的元素为((i,j))

    记录(rnkr_{i,j})表示((i,j))是第(i)行中第几小的(即它将在第(i)行中获得的编号),(rnkc_{i,j})表示((i,j))是第(j)列中第几小的(即它将在第(j)列中获得的标号)。

    再记录(mxr_{i})表示第(i)行中有多少不同的元素(即第(i)行中最大的元素是第几小的),(mxc_i)表示第(i)列中有多少不同的元素(即第(j)列中最大的元素是第几小的)。

    那么显然,我们考虑第(i)行第(j)列的时候,((i,j))获得的编号将是(max(rnkr_{i,j},rnkc_{i,j}))

    我们设((i,j))获得的编号为(id)

    那么为了满足相对大小不变,第(i)行中比((i,j))大的元素的编号将增大(id-rnkr_{i,j}),则第(i)行中最大的编号将是(mxr_i+(id-rnkr_{i,j}));

    同理,为了满足相对大小不变,第(j)列中比((i,j))大的元素的编号将增大(id-rnkc_{i,j}),则第(j)列中最大的编号将是(mxc_j+(id-rnkc_{i,j}))

    于是答案就是上面两个东西的较大值了。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    struct CMP{
    	int id,v;
    }c[1010];
    int n,m,a[1010][1010],rnkr[1010][1010],rnkc[1010][1010],mxr[1010],mxc[1010],t;
    bool cmp(CMP x,CMP y){
    	return x.v<y.v;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)scanf("%d",&a[i][j]);
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j)c[j]=(CMP){j,a[i][j]};
    		sort(c+1,c+m+1,cmp);
    		for(int j=1;j<=m;++j)c[j].v>c[j-1].v?++mxr[i]:0,rnkr[i][c[j].id]=mxr[i];
    	}
    	for(int i=1;i<=m;++i){
    		for(int j=1;j<=n;++j)c[j]=(CMP){j,a[j][i]};
    		sort(c+1,c+n+1,cmp);
    		for(int j=1;j<=n;++j)c[j].v>c[j-1].v?++mxc[i]:0,rnkc[c[j].id][i]=mxc[i];
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j){
    			t=max(rnkr[i][j],rnkc[i][j]);
    			printf("%d ",max(mxr[i]+(t-rnkr[i][j]),mxc[j]+(t-rnkc[i][j])));
    		}
    		puts("");
    	}
    	return 0;
    }
    

    D. Camp Schedule

    AC时间:1h24min,1413分(-1)

    题解:

    发现一定是贪心地一个一个地排(t),直到不能排为止。

    但是前一个(t)和后一个(t)可能会有重叠部分。

    重叠部分最多是多少呢?

    就是(t)的border,即(t)最长的前缀等于后缀的部分啦。

    border怎么求呢?

    跑一遍kmp就好啦。

    然后呢?

    我们以一个(t)串为基础,将(t)的border以后的部分不停地加入,直到不能再加就好了。

    什么时候不合法呢?

    1.剩下的长度不够放了;

    2.放完后串的1的数量大于(s)中1的数量,或者0的数量大于(s)中的0数量。

    注意:有可能连一个(t)也放不下,即(t)的长度大于(n),或(t)中1的数量大于(s)中1的数量,或者是(t)中0的数量大于(s​)中0的数量。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    char s[500010],t[500010],p[500010];
    int n,m,t1,tmp,nw,nxt[500010],len;
    void getnxt(){
    	nxt[1]=0;
    	nw=0;
    	for(int i=2;i<=n;i++){
    		while(nw!=0&&t[nw+1]!=t[i])nw=nxt[nw];
    		if(t[nw+1]==t[i])nxt[i]=++nw;
    		else nxt[i]=nw;
    	}
    }
    int main(){
    	scanf("%s%s",s+1,t+1);
    	n=strlen(s+1),m=strlen(t+1);
    	if(m>n)return(printf("%s",s+1),0);
    	getnxt(),len=nxt[m];
    	for(int i=1;i<=n;++i)t1+=s[i]=='1';
    	for(int i=1;i<=m;++i)tmp+=t[i]=='1';
    	if(tmp>t1)return(printf("%s",s+1),0);
    	if(n-m+tmp<t1)return(printf("%s",s+1),0);
    	for(int i=1;i<=m;++i)p[i]=t[i];
    	t1-=tmp,tmp=0,nw=len+1;
    	for(int i=1+len;i<=m;++i)tmp+=t[i]=='1';
    	for(int i=m+1;i<=n;++i,nw=(nw==m?len+1:nw+1)){
    		if(t[nw]=='0'){
    			if(n-i+1==t1){
    				for(int j=i;j<=n;++j)p[j]='1';
    				break;
    			}else p[i]='0';
    		}else{
    			if(!t1){
    				for(int j=i;j<=n;++j)p[j]='0';
    				break;
    			}else p[i]='1',--t1;
    		}
    	}
    	printf("%s",p+1);
    	return 0;
    }
    

    总结

    本场难度:E>F>D>B>C>A

    下一场打Div.1就会掉回(color{blue}{蓝})名了QWQ

  • 相关阅读:
    HDU 4714:Tree2cycle 树形DP
    HDU 4679:Terrorist’s destroy 树形DP
    as 和is的区别
    关于父类引用指向子类对象
    C# new的用法
    Mvc中把list从View传入Controller
    Html.TextBoxFor三元判断
    ref 和out的用法以及区别
    c# datatable list 相互转换
    jquery trigger伪造a标签的click事件取代window.open方法
  • 原文地址:https://www.cnblogs.com/xryjr233/p/CF1138.html
Copyright © 2011-2022 走看看