[Codeforces] Round #595 (Div. 3) A B1 B2 C1 C2 D1 D2 E

A: 将数分为k组使得每组不包含数值差为1的数

解:正整数可直接分为两组 奇数 偶数 符合题意, 所以给定数列有相邻就是2否则就是1


B1 / B2: 给定一每个点出度为1的图问每个点走到自己需要多少步

明显走到自己是个环, 并且环上答案都一样,递归求解即可

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e6 + 10;
typedef long long ll;
typedef long double ld;
const ll MOD = 1e9 + 7;
const int MX = 1e3 + 7;
int to[MAXN] = {0};
int ans[MAXN] = {0};
int step = 0, fa = 0;
void get(int now)
{
	int rto = to[now];
	++step;
	if(rto != fa)
	{
		get(rto);
	}
	ans[now] = step;
}
int main()
{ 
	//ios::sync_with_stdio(0);
	//cin.tie(0); cout.tie(0);
	//freopen("1.txt", "r", stdin);
	int q;
	cin >> q;
	while(q--)
	{
		int n;
		cin >> n;
		fill(ans, ans + n + 10, 0);
		for(int i = 1; i <= n; ++i)
		{
			cin >> to[i];
		}
		for(int i = 1; i <= n; ++i)
		{
			if(!ans[i])
			{
				step = 0, fa = i;
				get(i);
			}
		}
		for(int i = 1; i <= n; ++i)
		{
			cout << ans[i] << ' ';
		}
		cout << '\n';
	}
	
	
    return 0;
}

 C:问最靠近N的三进制数

先找一个大于N的满三进制数, 从大往小贪心删除即可

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 10;
typedef long long ll;
typedef long double ld;
const ll MOD = 1e9 + 7;
 
ll arr[MAXN] = {1}, p = 1;
ll pre[MAXN] = {1};
ll a[MAXN] = {0}, pa = 0, b[MAXN] = {0}, pb = 0;
 
int main()
{ 
	//ios::sync_with_stdio(0);
	//cin.tie(0); cout.tie(0);
	//freopen("1.txt", "r", stdin);
	for(int i = 1; ; ++i)
	{
		arr[p++] = arr[i - 1] * 3;
		pre[i] = pre[i - 1] + arr[i];
		//cout << arr[i] << ' ' << pre[i] << '\n';
		if(arr[i] > 1e18)
			break;
	}
	int q;
	cin >> q;
	while(q--)
	{
		ll n, sum;
		cin >> n;
		int rp = lower_bound(pre, pre + p, n) - pre;
		sum = pre[rp];
		for(int i = rp; i >= 0; --i)
		{
			if(sum - arr[i] >= n)
				sum -= arr[i];
		}
		cout << sum << '\n';
		
	}
    return 0;
}

 D1/D2: 给定一堆线段,问删最少的线段数使得每个点被覆盖最多k次

维护一个滑窗set保存覆盖当前点的所有线段 遍历全部点更新答案

 首先当前点被覆盖多余k次 则无论如何也需要删掉当前点上的x - k条线段,这x - k条线段越往右延伸覆盖到下一个点的几率越大,所以每次碰见多k次的点,就把滑窗中最靠右的几个线段删掉并记录答案即可

对于每个点的覆盖次数, 可以用树状数组 / 线段树维护区间加和单点查询维护

/*
    Zeolim - An AC a day keeps the bug away
*/
 
//#pragma GCC optimize(2)
//#pragma GCC ("-W1,--stack=128000000")
#include <bits/stdc++.h>
using namespace std;
#define mp(x, y) make_pair(x, y)
#define fr(x, y, z) for(int x = y; x < z; ++x)
#define pb(x) push_back(x)
#define mem(x) memset(x, 0, sizof(x))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair <int, int> pii;
typedef std::vector <int> vi;
//typedef __int128 ill;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 386910137;
const ull P = 13331; 
const int MAXN = 2e5 + 1e4;
const int MX = 2e5 + 10;
int n, k;
 
struct bit
{
	int c[MAXN << 1];
	
	int lowbit(int pos)	{return pos & -pos;}
	void add(int pos, int val)
	{ for( ; pos <= MX; pos += lowbit(pos)) c[pos] += val; }
	int ask(int pos)
	{
		int ret = 0; 
        for( ; pos; pos -= lowbit(pos)) ret += c[pos];
		return ret;
	}
};
 
struct line
{
	int x, y, id;
	bool operator < (const line b) const { return y >= b.y; }
}lin[MAXN];
 
bool cmp(line a, line b) { return a.x < b.x; }
 
int main()
{ 
	//ios::sync_with_stdio(0);
	//cin.tie(0); cout.tie(0);
	//freopen("1.txt", "r", stdin);
	
	bit T;
	cin >> n >> k;
	
	for(int i = 1; i <= n; ++i)
	{
		int x, y;
		cin >> x >> y;
		lin[i] = line{x, y, i};
		T.add(x, 1);
		T.add(y + 1, -1);
	}
	sort(lin + 1, lin + n + 1, cmp);
	vector <int> ans;
	int p = 1;
	set <line> ST;
	for(int i = 1; i <= MX && p <= n; ++i)
	{
		int x = T.ask(i);
		while(lin[p].x == i) { ST.insert(lin[p++]); }
		auto it = ST.end();
		while(ST.size() && (--it)->y < i)
		{
			ST.erase(it);
			it = ST.end();
		}
		while(x > k)
		{
			it = ST.begin();
			ans.push_back(it->id);
			T.add(it->x, -1);
			T.add(it->y + 1, 1);
			ST.erase(it);
			--x;
		}
	}
	cout << ans.size() << '\n';
	for(auto x : ans) { cout << x << ' '; }
    return 0;
}

 E 给两个数组 数组a是从i层到i+1层走路的时间, 数组b是从i层到i+1层坐电梯的时间,但是如果当前不在电梯里,需要等待c秒开门时间 问到达每层的最小时间

DP[MAXN][2]代表到第i层是走楼梯 0 还是坐电梯 1 走楼梯直接转移 坐电梯转移楼梯状态就需要加c秒等待时间

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 10;
typedef long long ll;
typedef long double ld;
const ll MOD = 1e9 + 7;

ll ra[MAXN], rb[MAXN];
ll dp[MAXN][2] = {0};
 
int main()
{ 
	//ios::sync_with_stdio(0);
	//cin.tie(0); cout.tie(0);
	//freopen("1.txt", "r", stdin);
 
	ll n, c;
	
	cin >> n >> c;
	
	for(int i = 1; i < n; ++i)
		cin >> ra[i];
		
	for(int i = 1; i < n; ++i)
		cin >> rb[i];
		
	dp[0][1] = c;
	for(int i = 1; i < n; ++i)
	{
		dp[i][0] = min(dp[i - 1][0] + ra[i], dp[i - 1][1] + ra[i]);
		dp[i][1] = min(dp[i - 1][1] + rb[i], dp[i - 1][0] + rb[i] + c);
		
	}
	
	for(int i = 0; i < n; ++i)
	{
		cout << min(dp[i][0], dp[i][1]) << ' ';
	}
	
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值