zoukankan      html  css  js  c++  java
  • Codeforces Round #704 (Div. 2)

    Codeforces 难得有一次不熬夜的比赛。

    比赛链接

    官方 Tutorial

    A

    送分题,记得开 long long。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define int long long
    signed main()
    {
    	int T;
    	scanf("%lld",&T);
    	while(T--)
    	{
    		int p,a,b,c;
    		scanf("%lld %lld %lld %lld",&p,&a,&b,&c);
    		int ta=(p+a-1)/a*a,tb=(p+b-1)/b*b,tc=(p+c-1)/c*c;
    		printf("%lld
    ",min(min(ta-p,tb-p),tc-p));
    	}
    	return 0;
    }
    

    B

    (sumlimits_{i = 1}^{n}{n^{n - i} cdot p_i}) 可以看作是一个 (n) 进制数,所以 (p_1) 越大越好,其次是 (p_2),以此类推。从 (n)(1) 枚举,如果当前的数能够安排到前面就安排到前面,按照题意模拟即可。时间复杂度 (mathcal O(n))(如果实现的好)。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int N=1e5;
    int a[N+10],p[N+10]; 
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		int n;
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++) 
    		{
    			scanf("%d",&a[i]);
    			p[a[i]]=i;
    		}
    		int pos=n+1;
    		vector<int> ans;
    		for(int i=n;i;i--)
    		{
    			for(int j=p[i];j<pos;j++) 
    				ans.push_back(a[j]);
    			if(p[i]<pos) pos=p[i];
    		}
    		for(int i=0;(unsigned)i<ans.size();i++) printf("%d ",ans[i]);
    		putchar('
    ');
    	}
    	return 0;
    }
    

    C

    分别对 (s) 从前往后和从后往前扫一遍求出 (pre_i)(suf_i)(pre_i) 表示在 (s) 中能够满足 (forall kin[1,i],s_{j_k}=t_k) 的子序列 (s_{j_1}s_{j_2}cdots s_{j_i})(1le j_1<j_2<cdots< j_ile n)) 中最小的 (j_i)(suf_i) 表示最大的 (j_i),答案就是 (maxlimits_{i=1}^{m-1} {suf_{i+1}-pre_i})

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=2e5;
    char s[N+10],t[N+10];
    int pre[N+10],suf[N+10]; 
    int main()
    {
    	int n,m;
    	scanf("%d%d%s%s",&n,&m,s+1,t+1);
    	for(int i=1,j=1;i<=n&&j<=m;i++)
    	{
    		if(s[i]==t[j])
    		{
    			pre[j]=i;
    			j++;
    		}
    	}
    //	for(int i=1;i<=m;i++) printf("%d ",pre[i]);/
    	for(int i=n,j=m;i&&j;i--)
    	{
    		if(s[i]==t[j])
    		{
    			suf[j]=i;
    			j--;
    		}
    	}
    	int ans=0;
    	for(int i=1;i<n;i++)
    		ans=max(ans,suf[i+1]-pre[i]);
    	printf("%d",ans);
    	return 0;	
    }
    

    D

    希望出题人没事。

    (x) 的二进制表示成 (x_1x_2cdots x_{a+b})(y) 表示成 (y_1y_2cdots y_{a+b})。令 (x_1=y_1=1)(x_{a+b-k}=y_{a+b}=1),然后把所有剩余的 (1) 安排在满足 (a_i=b_i=0) 的位置上即可。如果有任意一个步骤无法满足,则输出 Noreturn 0

    要特判 (old{k=0})(old{a=0}) 的情况。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5;
    int x[N+10],y[N+10];
    int main()
    {
    	int a,b,k;
    	scanf("%d %d %d",&a,&b,&k);
    	swap(a,b);
    	int n=a+b;
    	int ta=a,tb=b;
    	if(k==0)
    	{
    		puts("Yes");
    //		ta--;
    		for(int i=1;i<=ta;i++) putchar('1');
    		for(int i=1;i<=tb;i++) putchar('0');
    		putchar('
    '); 
    		for(int i=1;i<=ta;i++) putchar('1');
    		for(int i=1;i<=tb;i++) putchar('0');
    		return 0;
    	}
    	if(b==0)
    	{
    		if(k!=0)
    		{
    			puts("No");
    			return 0;
    		}
    		else
    		{
    			puts("Yes");
    			for(int i=1;i<=a;i++) putchar('1');
    			putchar('
    ');
    			for(int i=1;i<=a;i++) putchar('1');
    			putchar('
    ');
    		}
    	}
    	x[1]=y[1]=1;
    	ta--;
    	if(ta<0)
    	{
    		puts("No");
    		return 0;
    	}
    	if(n-k<=1) 
    	{
    		puts("No");
    		return 0;
    	}
    	x[n-k]=y[n]=1;
    	ta--;
    	if(ta<0)
    	{
    		puts("No");
    		return 0;
    	}
    	for(int i=1;i<=n&&ta;i++)
    	{
    		if(!x[i]&&!y[i])
    		{
    			x[i]=y[i]=1;
    			ta--;
    		}
    	}
    //	if(ta>0)
    //	{
    //		puts("No");
    //		return 0;
    //	}
    	printf("Yes
    ");
    	for(int i=1;i<=n;i++) printf("%d",x[i]);
    	putchar('
    ');
    	for(int i=1;i<=n;i++) printf("%d",y[i]);
    }
    

    E

    定义两行之间的差异值 (mathrm{diff}(x,y)=sumlimits_{i=1}^m[s_{x,i} ot=s_{y,i}])。令 (w=maxlimits_{i=2}^n{mathrm{diff(1,i)}})(id) 表示取到 (w) 的行的编号,接下来就是 喜 闻 乐 见 的分类讨论:

    1. (wle 2),直接输出第一行即可;
    2. (wge 5),无解;
    3. (w=4),则第一行与第 (id) 行一定都与答案的 (mathrm{diff}) 都是 (2),枚举第 (id) 行哪两个数是正确的,将它们 copy 到第一行中,不断验证当前答案是否正确,如果不正确就还原初始状态,继续枚举;
    4. (w=3),则第一行与第 (id) 行分别有一个答案是正确的,有一个答案都无法确定是否是正确的。枚举都正确的那两个数,将第 (id) 行正确的数 copy 到第一行中,然后假设第一行无法确定的数是正确的,验证一遍,如果存在一行 (x) 使得 (mathrm{diff}ge 3) 就把第 (x) 行于第一行无法确定的数同列的数 copy 到第一行中并再验证一遍,如果还是不行就还原初始状态,继续枚举。

    情况三最多验证 (mathrm{C}_4^2=6) 遍,情况四最多验证 (2mathrm{C}_3^2=6) 遍,是两个可以接受的常数。总的时间复杂度是 (mathcal O(nm))

    #include<bits/stdc++.h>
    using namespace std;
    const int N=250000;
    vector<int> a[N+10];
    int n,m;
    int dif(vector<int> x,vector<int> y)
    {
    	int ans=0;
    	for(int i=1;i<=m;i++)
    		ans+=(x[i]!=y[i]);
    	return ans;
    }
    bool check()
    {
    	for(int i=2;i<=n;i++)
    		if(dif(a[1],a[i])>2)
    			return false;
    	return true;
    }
    int check1()
    {
    	for(int i=2;i<=n;i++)
    		if(dif(a[1],a[i])>2)
    			return i;
    	return 0;
    }
    int pos[N+10],cnt=0;
    int main()
    {
    	// int n,m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		a[i].push_back(0);
    		for(int j=1;j<=m;j++)
    		{
    			int x;
    			scanf("%d",&x);
    			a[i].push_back(x);
    		}
    	}
    	int mx=0,id=-1;
    	for(int i=2;i<=n;i++)
    	{
    		int tmp=dif(a[1],a[i]);
    		if(tmp>mx)
    		{
    			mx=tmp;
    			id=i;
    		}
    	}
    	if(mx<=2)
    	{
    		puts("Yes");
    		for(int i=1;i<=m;i++) printf("%d ",a[1][i]);
    	}
    	else if(mx>=5)
    		puts("No");
    	else if(mx==4)
    	{
    		for(int i=1;i<=m;i++)
    			if(a[1][i]!=a[id][i])
    				pos[++cnt]=i;
    		for(int i=1;i<=cnt;i++)
    		{
    			for(int j=i+1;j<=cnt;j++)
    			{
    				int pi=pos[i],pj=pos[j];
    				int ti=a[1][pi],tj=a[1][pj];
    				a[1][pi]=a[id][pi];
    				a[1][pj]=a[id][pj];
    				if(check())
    				{
    					puts("Yes");
    					for(int i=1;i<=m;i++) printf("%d ",a[1][i]);
    					return 0;
    				}
    				a[1][pi]=ti;
    				a[1][pj]=tj;
    			}
    		}
    		puts("No");
    	}
    	else if(mx==3)
    	{
    		for(int i=1;i<=m;i++)
    			if(a[1][i]!=a[id][i])
    				pos[++cnt]=i;
    		// printf("pos:
    ");
    		// for(int i=1;i<=cnt;i++) printf("%d ",pos[i]);
    		for(int i=1;i<=cnt;i++)
    		{
    			for(int j=1;j<=cnt;j++)
    			{
    				if(i==j) continue;
    				int pi=pos[i],pj=pos[j],pk=pos[6-i-j];
    				int ti=a[1][pi],tj=a[1][pj],tk=a[1][pk];
    				// a[1][pi]=a[id][pi];
    				a[1][pj]=a[id][pj];
    				int tmp=check1();
    
    				if(!tmp)
    				{
    					puts("Yes");
    					for(int i=1;i<=m;i++) printf("%d ",a[1][i]);
    					return 0;
    				}
    				a[1][pk]=a[tmp][pk];
    				tmp=check1();
    				if(!tmp)
    				{
    					puts("Yes");
    					for(int i=1;i<=m;i++) printf("%d ",a[1][i]);
    					return 0;
    				}
    				a[1][pi]=ti;
    				a[1][pj]=tj;
    				a[1][pk]=tk;
    			}
    		}
    		puts("No");
    	}
    	return 0;
    }
    
  • 相关阅读:
    WebService-.Net:添加web引用和添加服务引用有什么区别?
    袁氏-人物-科学家:袁隆平(首届国家最高科学技术奖得主、杂交水稻之父)
    术语-BLOB:BLOB
    术语-PM:PM/项目管理 百科
    计算机:SAP (服务访问点(Service Accessing point))
    服务器-Web服务器-Tengine:Tengine 百科
    笔记-Git:Git 笔记
    DB-MDM:MDM/主数据管理 百科
    DB-MD:MD/主数据
    [Ext JS 4] 实战之 带week(星期)的日期选择控件
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/14438976.html
Copyright © 2011-2022 走看看