2018"百度之星"程序设计大赛 - 资格赛-1001,1002,1006

1001-调查问卷

思路:暴力所有问题集即1-->(1<<m)-1,先预处理将AB转换为二进制10,例如AA为二进制11,保存为3。遍历问题集s,将所有试卷集也s的与运算结果t用map<int,int> imap保存下来,imap[t]++;这样所有的试卷结果都分开了,再计算不同试卷的对数即可。

Code :

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
using namespace std;

const int MAX_N=1055;
int n,m,p,T;
string a[MAX_N];
int d[MAX_N];

int main()
{
	ios::sync_with_stdio(false);
	cin>>T;
	for(int k=1;k<=T;++k){
		cin>>n>>m>>p;
		for(int i=0;i<n;++i)
			cin>>a[i];
		for(int i=0;i<n;++i)
		{
			int x=0;
			for(int j=0;j<a[i].size();++j)
				if(a[i][j]=='A')	x=x*2+1;
				else	x=x*2;
			d[i]=x;
		}
		int ans=0;
		int sum=pow(2,m);
		for(int i=1;i<sum;++i)
		{
			map<int,int> imap;
			for(int j=0;j<n;++j)
			{
				int t=i&d[j];
				imap[t]++;
			}
			int ss=0,si=0;
			for(auto c:imap)	//计算不同试卷的对数 
				if(c.second)
				{
					si+=c.second;
					ss+=c.second*(n-si);
				}
			if(ss>=p)	ans++;
		}
		cout<<"Case #"<<k<<": "<<ans<<endl; 
	}
	
	return 0;
}

1002-子串查询

思路:对于s[l,r]中的最小字典序子串即为按照a-z的顺序s[l,r]中存在的那个,因此可以预处理出a-z所有出现的下标分开保存,在遍历a-z,二分查找即可。

另一思路是可以用数组分别将a-z的前缀和保存下来,直接查询即可

code  二分:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

int n,Q,T;
string str;

int main()
{
	ios::sync_with_stdio(false);
	cin>>T;
	for(int t=1;t<=T;++t)
	{
		vector<int> ive[30];
		cin>>n>>Q>>str;
		for(int i=0;i<n;++i)
			ive[str[i]-'A'].push_back(i+1);
		cout<<"Case #"<<t<<":"<<endl;
		int l,r;
		while(Q--){
			cin>>l>>r;
			int ans=0;
			for(int i=0;i<26;++i)
				if(ive[i].size()){
					int t1=lower_bound(ive[i].begin(),ive[i].end(),l)-ive[i].begin();
					int t2=lower_bound(ive[i].begin(),ive[i].end(),r+1)-ive[i].begin();
					if(t1!=ive[i].size()&&ive[i][t1]<=r){
						ans=t2-t1;	break;
					}
				}
			cout<<ans<<endl;
		} 
	}
	
	return 0;
}

code  数组:

#include<iostream>
using namespace std;

const int MAX_N=100005;
int n,Q,T;
string str;
int d[30][MAX_N];

int main()
{
	ios::sync_with_stdio(false);
	cin>>T;
	for(int t=1;t<=T;++t)
	{
		cin>>n>>Q>>str;
		for(int i=0;i<n;++i)
			for(int j=0;j<26;++j)
				if((str[i]-'A')==j)	d[j][i+1]=d[j][i]+1;
				else	d[j][i+1]=d[j][i];
		cout<<"Case #"<<t<<":"<<endl;
		int l,r;
		while(Q--){
			cin>>l>>r;
			int ans=0;
			for(int i=0;i<26&&!ans;++i)
				ans=d[i][r]-d[i][l-1];
			cout<<ans<<endl;
		} 
	}
	
	return 0;
}

1006-三原色图

思路:大致思路就是分红绿,蓝绿两次分别查找最小生成树s1,s2,在将剩下的边由小到大排序v1,v2,每次取s1+v1[i],s2+v2[i]的最小值输出即可

Code :

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

struct node{
	int u;
	int v;
	int w;
	char c;
	bool operator<(const node &p)const{
		return w<p.w;
	}
};
const int MAX_N=105;
int n,m,T;
int id[MAX_N];
vector<node> e;
vector<int> v1,v2;

int Find(int x);
int Kruskal(char c);
int main()
{
	ios::sync_with_stdio(false);
	cin>>T;
	for(int t=1;t<=T;++t)
	{
		e.clear();	v1.clear();	v2.clear();
		cin>>n>>m;
		int u,v,w;
		char c;
		for(int i=0;i<m;++i)
		{
			cin>>u>>v>>w>>c;
			e.push_back(node{u,v,w,c});
		}
		sort(e.begin(),e.end());
		int s1=Kruskal('R');
		int s2=Kruskal('B');
		vector<int> vv1,vv2;
		vv1.push_back(0);	vv2.push_back(0);
		for(int i=0,k=0;i<m&&s1!=-1;++i)
			if(k<n-1&&e[i].w==v1[k])	++k;
			else	vv1.push_back(e[i].w);
		for(int i=0,k=0;i<m&&s2!=-1;++i)
			if(k<n-1&&e[i].w==v2[k])	++k;
			else	vv2.push_back(e[i].w);
		int boo=3;
		if(s1==-1&&s2==-1)	boo=0;
		else	if(s2==-1)	boo=1;
		else	if(s1==-1)	boo=2;
		cout<<"Case #"<<t<<":"<<endl;
		int sum1=0,sum2=0;
		for(int i=1;i<=m;++i)
			if(i<n-1)	cout<<-1<<endl;
			else{
				int ans=-1;
				if(boo==3){
					sum1+=vv1[i-n+1];	sum2+=vv2[i-n+1];
					ans=min(s1+sum1,s2+sum2);
				}else	if(boo==2){
					sum2+=vv2[i-n+1];	ans=s2+sum2;
				}else if(boo==1){
					sum1+=vv1[i-n+1];	ans=s1+sum1;
				}
				cout<<ans<<endl;
			}
	}
	
	return 0;
}

int Find(int x)
{
	if(id[x]!=x)	id[x]=Find(id[x]);
	return id[x];
}

int Kruskal(char c)
{
	for(int i=0;i<=n;++i)
		id[i]=i;
	int k=1,i=0,ans=0;
	while(k<n&&i<m){
		node t=e[i++];
		if(t.c!=c&&Find(t.u)!=Find(t.v)){
			id[Find(t.u)]=Find(t.v);
			if(c=='R')	v1.push_back(t.w);
			else	v2.push_back(t.w);
			ans+=t.w;	++k;
		}
	}
	if(k!=n)	ans=-1;
	return ans;
}

猜你喜欢

转载自blog.csdn.net/C_13579/article/details/81460277