首页 > 其他分享 >Codeforces Round 958 (Div. 2)

Codeforces Round 958 (Div. 2)

时间:2024-07-21 20:41:01浏览次数:8  
标签:958 typedef int Codeforces long pair Div include define

Preface

周末补题计划的最后一场,这场由于是最古早的所以有些题题意都记不太清了

赛时经典发病,前四题一题 WA 一发,然后把时间打没了 E 题经典没写完(中间还抽空写了个假做法),邮电部诗人了属于是


A. Split the Multiset

刚开始还感觉无从下手,写了个记搜交上去还 WA 了,后面发现每次分裂出 \(1\) 就是最优的

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=1005;
int t,n,k;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	scanf("%d%d",&n,&k),printf("%d\n",(n-1+k-2)/(k-1));
	return 0;
}

B. Make Majority

上来经典乱猜结论先挂一发后才能好好想题

不难发现操作一段区间如果得到的结果为 \(1\),则并不会使得 \(0,1\) 的个数差发生变化(如 \(101\to 1\),个数差保持在 \(1\) 个)

而唯一能减少个数差的操作只有把连续的一段 \(0\) 变成单独一个,因此先这样收缩完后比较 \(0,1\) 的个数即可

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=200005;
int t,n,pfx[N]; char s[N];
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i; scanf("%d%s",&n,s+1); int c[2]={0,0};
		for (i=1;i<=n;++i)
		if (s[i]=='1') ++c[1]; else
		if (s[i-1]!='0') ++c[0];
		puts(c[1]>c[0]?"Yes":"No");
	}
	return 0;
}

C. Increasing Sequence with Fixed OR

经典对着样例猜结论,通过观察发现序列长度最大为 \(n\) 在二进制下 \(1\) 的个数 \(+1\)

构造方案也很简单,从高到低将为 \(1\) 的位依次消去即可,最后补上 \(n\) 本身

由于不能出现 \(0\),因此要特判形如 \(2^k\) 的数,当然关于这个为什么是最优的建议去看 Tutorial

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
int t; LL n;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		scanf("%lld",&n);
		vector <LL> ans;
		for (RI i=60;i>=0;--i)
		if (((n>>i)&1)&&(n^(1LL<<i))!=0) ans.push_back(n^(1LL<<i));
		ans.push_back(n);
		printf("%d\n",ans.size());
		for (auto x:ans) printf("%lld ",x); putchar('\n');
	}
	return 0;
}

D. The Omnipotent Monster Killer

经典先乱搞一发 WA 了再猜结论,我愿称之为红温做题法

刚开始一波观察样例认为只需要两轮就能删完,因此就是跑一个树上最大权独立集,然后写完交上去就似了

后面手玩出了一组需要三轮操作的样例,本来准备把两轮改成三轮冲了,但后面还是冷静想了想感觉会有更多轮的情况

但直觉告诉我们这个轮数一定不会很多,对着一个链的情况画一画会感觉大概就是 \(\log\) 级别的轮数,实现时就直接取 \(20\) 了

因此此时把问题转化为,给树上的每个点赋一个权值 \(c_i\in [1,20]\),在满足任意两个相邻的点权值不同的情况下,最小化 \(\sum_{i=1}^n a_i\times c_i\)

很容易想到 DP,令 \(f_{i,j}\) 表示处理了 \(i\) 的子树,且 \(c_i=j\) 时子树内最小权值和,朴素的转移是 \(O(n\times 20^2)\) 的,但预处理下每个点的最大/次大值可以很容易做到 \(O(n\times 20)\) 的复杂度

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define int long long
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=300005;
int t,n,a[N],x,y,f[N][20],mn[N],smn[N]; vector <int> v[N];
inline void DP(CI now=1,CI fa=0)
{
	RI i; for (i=1;i<20;++i) f[now][i]=a[now]*i;
	for (auto to:v[now]) if (to!=fa)
	{
		for (DP(to,now),i=1;i<20;++i)
		if (mn[to]==f[to][i]) f[now][i]+=smn[to];
		else f[now][i]+=mn[to];
	}
	mn[now]=f[now][1]; smn[now]=f[now][2];
	if (mn[now]>smn[now]) swap(mn[now],smn[now]);
	for (i=3;i<20;++i)
	if (f[now][i]<mn[now]) smn[now]=mn[now],mn[now]=f[now][i];
	else if (f[now][i]<smn[now]) smn[now]=f[now][i];
}
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%lld",&t);t;--t)
	{
		RI i; int sum=0; for (scanf("%d",&n),i=1;i<=n;++i)
		scanf("%lld",&a[i]),v[i].clear(),sum+=a[i];
		for (i=1;i<n;++i)
		scanf("%lld%lld",&x,&y),v[x].push_back(y),v[y].push_back(x);
		DP(); printf("%lld\n",mn[1]);
	}
	return 0;
}

E. Range Minimum Sum

比赛的时候抽风了一个弯没绕过了,然后就释怀地似了

没有删除元素的时候做法很多,大致思路都是一致的,即找到每个位置左边/右边第一个小于该元素的位置 \(l_i/r_i\),实现时可以用单调栈(笛卡尔树)或 set 处理

先计算出起始时的答案,并考虑修改一个位置 \(a_p\) 带来的影响:

  • 最小值为 \(a_p\) 的区间没了,这个贡献初始时就已经计算过了;
  • 对于一些 \(a_i<a_p\) 的位置,以 \(i<p\) 为例,若 \([i+1,p-1]\) 中没有 \(<a_i\) 的元素,则最小值为 \(a_i\) 的区间会少去一部分贡献,这部分实际上是个区间加,可以差分解决;
  • 对于一些 \(a_i>a_p\) 的位置,以 \(i<p\) 为例,当 \(a_p\) 被删掉后 \(a_i\) 为最小值的区间反而增加了;这类贡献在 \(a_i\) 处统计比较方便,即我们找到 \(>i\) 的第一个 \(<a_i\) 的位置 \(p\),并找出 \(>p\) 的第一个 \(<a_i\) 的位置 \(q\),那么 \(a_p\) 被删除时最小值为 \(a_i\) 的区间就会增多 \((q-p-1)\times (i-l_i)\),另一个方向同理;

总复杂度 \(O(n\log n)\),笛卡尔树合并的方法有机会再补

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define int long long
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=500005;
int t,n,a[N],d[N],pos[N],dlt[N],val[N];
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%lld",&t);t;--t)
	{
		RI i; for (scanf("%lld",&n),i=1;i<=n;++i)
		scanf("%lld",&a[i]),pos[a[i]]=i,d[i]=dlt[i]=0;
		set <int> s; s.insert(0); s.insert(n+1);
		int sum=0; for (i=1;i<=n;++i)
		{
			int p=pos[i],L=*(--s.lower_bound(p)),R=*s.upper_bound(p);
			val[p]=i*(p-L)*(R-p); sum+=val[p];
			auto upt=[&](CI l,CI r,CI mv)
			{
				d[l]+=mv; d[r+1]-=mv;
			};
			if (L+1<=p-1) upt(L+1,p-1,-i*(R-p));
			if (p+1<=R-1) upt(p+1,R-1,-i*(p-L));
			auto it=s.lower_bound(p);
			if (it!=s.begin())
			{
				if (--it!=s.begin())
				{
					auto pre=it; --pre;
					dlt[*it]+=i*(*it-*pre-1)*(R-p);
				}
			}
			it=s.upper_bound(p);
			if (it!=s.end())
			{
				auto nxt=it; ++nxt;
				if (nxt!=s.end())
				{
					dlt[*it]+=i*(*nxt-*it-1)*(p-L);
				}
			}
			s.insert(p);
		}
		for (i=1;i<=n;++i) d[i]+=d[i-1];
		for (i=1;i<=n;++i) printf("%lld%c",sum-val[i]+d[i]+dlt[i]," \n"[i==n]);
	}
	return 0;
}

Postscript

感觉最近的训练强度有点大了,好多题都没来得及补就要开始新一周的训练了,不过还是很充实的说

标签:958,typedef,int,Codeforces,long,pair,Div,include,define
From: https://www.cnblogs.com/cjjsb/p/18314923

相关文章

  • Codeforces Round 959 sponsored by NEAR (Div. 1 + Div. 2)
    Preface这场比赛的时候CF一直抽风,快10min的时候才登上去,然后中间交题也一直在人机验证50min左右过了前5题后,F没想到生成树当场趋势了,赛后发现原来是原题大战可海星A.DiverseGame将每个数循环移位变为下一个数即可,注意特判\(n=m=1\)的情形#include<cstdio>#incl......
  • Codeforces Round 958 (Div. 2)
    A.SplittheMultisetForexample, {2,2,4} isamultiset.Youhaveamultiset ......
  • Codeforces Round 960 (Div. 2)(A - D)
    CodeforcesRound960(Div.2)(A-D)A-SubmissionBait解题思路:假设直接选最大数,如果最大数有奇数个,\(Alice\)必胜,反之必败。根据这个思路,从大到小看数字,找到第一个出现奇数次的数,从它开始选,就能保证每次\(Alice\)选的时候还剩奇数个选项。代码:#include<bits/stdc++.......
  • Codeforces Round 960 (Div. 2)
    Preface周日开始补之前欠下的CF博客,这周一共有三场就按照从后往前的顺序补吧这场经典前期唐完了,前4题上来每题WA一发也是神人了,最后做到E的时候只有50min了结果还把题看错了以为树的形态都是不确定的,怀疑人生了好久感觉这个题完全没法做,后面看了眼样例才发现树的形态......
  • Codeforces Round 960(Div.2)
    CodeforcesRound960(Div.2)A从大到小去判断数字个数的奇偶性,只要出现过奇数,先手必赢,如果不出现奇数,后手必赢#include<iostream>#include<queue>#include<map>#include<set>usingnamespacestd;constintN=55;inta[N];voidsolve(){ intn; cin>>n; ma......
  • 题解:Codeforces Round 960 (Div. 2) D
    D.GridPuzzletimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputYouaregivenanarray\(a\)ofsize\(n\).Thereisan\(n\timesn\)grid.Inthe\(i\)-throw,thefirst\(a_i\)......
  • 题解:Codeforces Round 960 (Div. 2) C
    C.MadMADSumtimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputWedefinethe\(\operatorname{MAD}\)(MaximumAppearingDuplicate)inanarrayasthelargestnumberthatappearsatleast......
  • Codeforces
    Round959A给定\(n*m\)数组\(a\),$1\lea_i\len*m$并且两两不同,问是否存在数组\(b\),也使用这些元素,并且每个位置的值都与\(a\)不同。\(1*1\)数组特判,其他循环移位。B给定01串s和t,可以对s任意次执行以下操作:选择l,r,将l,r异或等长前缀,问s和t是否能相等对于s和t第一个......
  • Codeforces Round 960 (Div. 2) A - D
    link好图好图qwq这次也是终于装上插件codeforcesbetter!了,妈妈再也不用担心我的英语啦A-SubmissionBaitA先手,B后手,优先往奇偶性的方向想一开始我只是单纯考虑A总是选最大值的数的奇偶性,样例过了?交上去发现wa2然后恼...瞎搞了个33344,发现A可以先选3......
  • 题解:Codeforces Round 960 (Div. 2) B
    B.ArrayCrafttimelimitpertest:1secondmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputForanarray\(b\)ofsize\(m\),wedefine:themaximumprefixpositionof\(b\)isthesmallestindex\(i\)thatsat......