codeforce_div3_round490 ABCDEF

这一场也补的挺憋屈的···ABC很水,
D题思路很好想,按照余数把人进行分组,然后把每组多出来的人分配到其他组就好。于是想着,先for循环找到第一个人数比较多的,然后从这个位置开始for循环整整一圈,把多余的人都收集起来,补充到人不够的地方。但是写的差不多了才发现这样做可能会导致这个位置现在需要的人数可能比我现在找到的多出来的人要多,导致补不上,虽然可以直接从下一组借人(毕竟怎么移动不影响答案),但是特判 太多,思路太乱,还是抄了标程······
E题思路也简单,直接根节点开始爆搜,标记自己现在能达到的点,剩下的没标记的点就都是自己的父节点或者不可达。然后对于所有的点,找到没标记的,继续爆搜,标记这个点能达到的所有点,然后count++, 然后WA了,百思不得其解,看标程。嗯·· 因为父节点也不是直接count++的,父节点也可能单向到达另一个父节点,所以不能直接爆搜,正解是贪心,对于每一个父节点,搜索其子节点的数量,根节点优先和子节点数量多的连接。嗯,抄答案。
F是DP,挺特殊的DP,首先是按照每个人喜欢的数字对人进行分组,然后这个DP,跟人的组数完全不相关。dp[x][y]表示都喜欢数字 L 的人有x个,分配一共y张包含他们喜欢的数字的卡牌的时候,最大的喜悦值。所有dp一次之后,res+=dp[ 数字i喜欢的人数 ][ 包含数字i的卡牌数量 ],嗯,强,上标称。
哭了哭了
A

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

int main()
{
    int n,k;cin>>n>>k;
    vector<int>a(n+1);
    for(int i=0;i<n;i++) cin>>a[i];
    int l=0,r=n-1,sum=0;
    while(a[l]<=k&&l<n){
		l++;
		sum++;
    }
    while(r>l&&a[r]<=k){
		r--;
		sum++;
    }
    cout<<sum<<endl;
    return 0;
}

B

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int n;string t; cin>>n>>t;
    for(int i=2;i<=n;i++){
		if(n%i==0){
			reverse(t.begin(),t.begin()+i);
		}
    }
    cout<<t<<endl;
    return 0;
}

C

#include <iostream>
#include <algorithm>
using namespace std;
const int N=4e5+10;
char a[N],b[N];
int f[30];
int main()
{

    int n,k;cin>>n>>k;
   cin>>a;
   for(int i=0;i<n;i++){
		f[a[i]-'a']++;
   }
   int now=0;
   while(k&&now<26){
		if(k>=f[now]) {k-=f[now]; f[now]=0; now++; }
		else {f[now]-=k; k=0; }
   }
   int len=0;
   for(int i=n-1;i>=0;i--){
		if(f[a[i]-'a']){
			f[a[i]-'a']--;
			b[len++]=a[i];
		}
   }
   reverse(b,b+len);
    cout<<b<<endl;
    return 0;
}

D:

#include <bits/stdc++.h>

using namespace std;

int main() {

	int n, m;
	cin >> n >> m;
	int k = n / m;
	vector<int> a(n);
	vector<vector<int>> val(m);//二维 按照余数把每一个数字分组
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
		val[a[i] % m].push_back(i);
	}

	long long ans = 0;
	vector<pair<int, int>> fre;//可以移动的数字
	for (int i = 0; i < 2 * m; ++i) {
		int cur = i % m;
		while (int(val[cur].size()) > k) {//当前余数中数字个数大于k
			int elem = val[cur].back();
			val[cur].pop_back();
			fre.push_back(make_pair(elem, i));//放入可移动
		}
		while (int(val[cur].size()) < k && !fre.empty()) {//当前余数中数字个数小于k
			int elem = fre.back().first;
			int mmod = fre.back().second;
			fre.pop_back();//取出元素
			val[cur].push_back(elem);
			a[elem] += i - mmod;//改变这个元素的余数
			ans += i - mmod;
		}
	}

	cout << ans << endl;
	for (int i = 0; i < n; ++i)
		cout << a[i] << " ";
	cout << endl;

	return 0;
}

E

#include <bits/stdc++.h>

using namespace std;

const int N = 5010;

int n, m, s;
vector<int> g[N];
bool used[N];
bool ok[N];//vis标记

int cnt;

void dfs1(int v) {
	ok[v] = true;
	for (auto to : g[v])
		if (!ok[to])
			dfs1(to);
}

void dfs2(int v) {
	used[v] = true;
	++cnt;
	for (auto to : g[v])
		if (!used[to] && !ok[to])
			dfs2(to);
}

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

	cin >> n >> m >> s;
	--s;
	for (int i = 0; i < m; ++i) {
		int x, y;
		cin >> x >> y;
		--x, --y;
		g[x].push_back(y);
	}

	dfs1(s);//到这里都一样

	vector<pair<int, int>> val;
	for (int i = 0; i < n; ++i) {
		if (!ok[i]) {
			cnt = 0;
			memset(used, false, sizeof(used));
			dfs2(i);
			val.push_back(make_pair(cnt, i));
		}
	}
	sort(val.begin(), val.end());
	reverse(val.begin(), val.end());

	int ans = 0;
	for (auto it : val) {
		if (!ok[it.second]) {
			++ans;
			dfs1(it.second);
		}
	}

	cout << ans << endl;

	return 0;
}

F

#include <bits/stdc++.h>

using namespace std;

const int N = 520;
const int K = 12;
const int C = 100 * 1000 + 11;

int n, k;
int c[C];
int f[C];
vector<int> h;

int dp[N][K * N];

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

	cin >> n >> k;
	h = vector<int>(k + 1);
	for (int i = 0; i < n * k; ++i) {
		int x;
		cin >> x;
		++c[x];
	}//按照数字记录卡片的数量
	for (int i = 0; i < n; ++i) {
		int x;
		cin >> x;
		++f[x];
	}//按照喜欢的数字对n个人进行分类计数
	for (int i = 1; i <= k; ++i)
		cin >> h[i];

	for (int i = 0; i < n; ++i) {
		for (int j = 0; j <= n * k; ++j) {//前i个人分到的数量
			for (int cur = 0; cur <= k; ++cur) {//第i+1个人分到的喜欢的卡牌数量
				dp[i + 1][j + cur] = max(dp[i + 1][j + cur], dp[i][j] + h[cur]);
			}
		}
	}

	int ans = 0;
	for (int i = 0; i < C; ++i) {
		if (f[i] != 0) ans += dp[f[i]][c[i]];
	}

	cout << ans << endl;

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值