Codeforces Round 479 #div3

刚开场卡了一会,凭借手速切出了前三题,,然后开始挂机。

D:点击打开链接

题意:给你n个数,这n个数是由每个数的前一个数*2,/3得到的(注意不是随机的,是按照一次乘2一次除3)。但是给你的这n个数是打乱的,要求恢复原本的顺序。

input
Copy
6
4 8 6 3 12 9
output
Copy
9 3 6 12 4 8 

思路一:全排列,然后判断。 打了一遍玩玩,最长100个数,100!,,复杂度耗不起。

思路二:找规律,想先找最小的和最大的,然后递推(没做出来)

思路三:参考别人的题解,每一个数都可以计算出它包含多少个因子2,多少个因子3。然后利用结构体排个序,很容易就可以得到结果。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 105;
ll n,nn,k;

struct node{
	ll two,three,num;
	bool operator<(const node &p)const
	{
		if(three==p.three)
			return two<p.two;
		return three>p.three;
	}
}a[maxn];

int main()
{
	cin>>nn;
	n = nn;
	int cnt = 0;
	while(n--)
	{
		node q;
		cin>>k;
		q.num = k;
		int x=0,y=0;
		while(k%3==0)
		{
			k /= 3;
			x++;
		}
		while(k%2==0)
		{
			k /= 2;
			y++;
		}
		q.two = y;
		q.three = x;
		a[cnt++] = q;
	}
	sort(a,a+cnt);
	for(int i=0;i<cnt;i++)
		cout<<a[i].num<<" ";
	cout<<endl;
	return 0;
}

第五题:点击打开链接

求有几个纯环(没有多余的边)。

思路:dfs,如果是纯环,那么一个节点有且只有2条边,其余看代码。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 200005;
int n,m,ans;
vector<int>E[maxn];
bool vis[maxn],flag;
void dfs(int x)
{
	if(E[x].size()!=2)	flag = false;
	for(int i=0;i<E[x].size();i++)
	{
		if(!vis[E[x][i]])
		{
			vis[E[x][i]] = 1;
			dfs(E[x][i]);
		}
	}
}

int main()
{
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int x,y;
		cin>>x>>y;
		E[x].push_back(y);
		E[y].push_back(x);
	}
	for(int i=1;i<=n;i++)
	{
		//memset(vis,0,sizeof(vis));
		if(!vis[i])
		{
			flag = 1;
			dfs(i);
			if(flag)
				ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
}

F题:点击打开链接

题目大意:输入n个数,求最大连续上升子序列(要记录序号)

真的是脑抽了,第一想法n^2dp,字符串瞎操作,果断TLE。。

#include<bits/stdc++.h>
#include<string>
using namespace std;
const int maxn = 200005;
typedef long long ll;

int n,ans,tot=0,pos;
ll a[maxn];
bool flag[maxn];
string s,sn;

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&a[i]);
	}
	ans = 0;
	for(int i=0;i<n;i++)
	{
		if(flag[i])	continue;
		flag[i] = 1;
		pos = a[i];
		tot = 1;
		sn.clear();
		string temp;
		stringstream ss;
		ss<<i+1;
		ss>>temp;
		sn += temp;
		for(int j=i;j<n;j++)
		{
			if(n-j+tot<ans) break;
			if(a[j]==pos+1)
			{
				tot++;
				pos = a[j];
				string temp;
				stringstream ss;
				ss<<j+1;
				ss>>temp;
				sn += temp;
			}
		}
		if(tot>ans) {
			ans = tot;
			s = sn;
		}
	}
	cout<<ans<<endl;
	for(int i=0;i<s.length();i++)
		cout<<s[i]<<" ";
	return 0;
}

然后参考别人做法,O(nlogn)的,用了map维护的DP。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 200005;

int n,a[maxn],pos,maxi=-1;
map<int,int> dp;

int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(int i=n-1;i>=0;i--)
	{
		dp[a[i]] = max(dp[a[i]],dp[a[i]+1]+1);
		if(dp[a[i]]>maxi)
		{
			maxi = dp[a[i]];
			pos = a[i];
		}
	}
	cout<<maxi<<endl;
	for(int i=0;i<n;i++)
	{
		if(a[i]==pos) {
			cout<<i+1<<" ";
			pos++;
		}
	}
	cout<<endl;
	return 0;
}
这场DIV3总体来说还是比较简单的,但我菜,需努力。

猜你喜欢

转载自blog.csdn.net/zxwsbg/article/details/80230284