首页 > 其他分享 >【CFVP】Codeforces Round 851 (Div. 2)

【CFVP】Codeforces Round 851 (Div. 2)

时间:2023-08-26 21:22:26浏览次数:39  
标签:851 int sum tree cin Div mx dp CFVP

前言

本场VP深感自己的弱小与史队的强大。

又一次被史队全方位暴打。

来做一个简要的总结。

正文

A. One and Two

A题日常的愚蠢。

考虑到原序列只含有质因子2。我们将质因子2平分给左右两边即可。当2的个数为奇数时即判断为无解。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int t,n,a[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		int num=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			num+=(a[i]==2);
		}
		int s=0;
		bool f=0;
		for(int i=1;i<=n;i++)
		{
			s+=(a[i]==2);
			if(s*2==num)
			{
				f=1;
				cout<<i<<endl;
				break;
			}
		}
		if(f==0)
		{
			cout<<-1<<endl;
		}
	}
	return 0;
} 

B. Sum of Two Numbers

B题是煞笔题,被罚了2次,也是习惯了。

考虑到原问题关于数字和,我们考虑拆数。接着将数字和平分给两个数即可。

需要注意前缀0的细节问题。

代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,a[11];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		int s=0,sum=0;
		while(n!=0)
		{
			a[++s]=n%10;
			sum+=a[s];
			n/=10;
		}
		int k=sum/2;
		if(sum%2==1)
		k++;
		for(int i=s;i>=1;i--)
		{
			if(k>=a[i])
			{
				k-=a[i];
				cout<<a[i];
				a[i]=0;
			}
			else
			{
				a[i]-=k;
				cout<<k;
				k=0;
			}
		}
		cout<<" ";	
		bool f=0;
		for(int i=s;i>=1;i--)
		{
			if(a[i]!=0||f==1)
			{
				f=1;
				cout<<a[i];
			}
		}
		if(f==0)
		{
			cout<<0;
		}
		cout<<endl;
	}
	return 0; 
}

C. Matching Numbers

C题是一道简单的构造题,数感好的话一下就看出来了。

不过这里还是严谨的证明一下。

首先,不难发现原题是想让我们用 \([1,2n]\) 两两配对求和成一个公差唯一的等差数列。对于该等差数列而言,它的平均数为 \(\frac{2n(2n+1)}{2n}=2n+1\) 。这是个奇数,因此,显然只有当 \(n\) 为奇数时有解。

接着我们考虑构造,为了使结果相对的均衡,我们希望让结果呈现一个 \([1,n]\) 与 \([n+1,2n]\) 一一映射的局面。由于奇数与偶数本质不同,因此我们将他们分开讨论,且当 \(n\) 为奇数时,显然奇数多于偶数。因此我们用与 \([1,n]\) 中的奇数配对的答案表示答案序列中不小于 \(2n+1\) 的部分。偶数凡是。考虑到奇数偶数增长的速度都是2,想要构造公差为1的序列,朴素的方式是除以2来考虑。

代码:

#include<bits/stdc++.h>
using namespace std;
int t,n;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		if(n%2==0)
		{
			cout<<"NO"<<endl;
			continue;
		}
		cout<<"YES"<<endl;
		for(int i=1;i<=n;i++)
		{
			cout<<i<<" ";
			int x=i/2;
			if(i%2==1)
			{
				x++;
				cout<<n*2-x+1;
			}
			else
			{
				int s=n/2;
				cout<<n+(s-x+1);
			}
			cout<<endl;
		}
	}
	return 0;
}

D. Moving Dots

再次无缘场切D题。

D是不擅长的计数,我发现我总是把计数题考虑得过于宏观。但其实本题的计数题套路非常常见。

我们考虑两个点在答案中产生贡献,当且仅当他们中间的点没有被选且他们异侧的点距离他们更远。

因此我们只需要枚举产生贡献的两个点,移除掉会影响他们的点,统计方案即可。若最终除他们外还剩 \(k\) 个点,贡献即为 \(2^k\)。

代码注意二分边界,以及lowerbound和upperbound的用法,最近总是搞错,警钟长鸣。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+100;
const int mod=1e9+7;
int n,a[N],pw[N],ans;
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	a[n+1]=INT_MAX;
	a[0]=INT_MIN;
	pw[0]=1;
	for(int i=1;i<=n;i++)
	{
		pw[i]=pw[i-1]*2;
		pw[i]%=mod;
	}
	for(int i=1;i<n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			int l=lower_bound(a+0,a+i+1,a[i]-(a[j]-a[i]))-a;
			l--; 
			int r=lower_bound(a+j,a+2+n,a[j]+(a[j]-a[i]))-a;
			ans+=(pw[l]*pw[n+1-r])%mod;
			ans%=mod;
		}
	}
	cout<<ans<<endl; 
	return 0;
}

E. Sum Over Zero

考虑本题的暴力dp做法,我们令 \(dp[i]\) 为前缀 \(i\) 的最大结果,令 \(sum[i]\) 表示前缀 \(i\) 的前缀和。对于 \(\forall j>i\)。若 \(sum[j]>=sum[i]\) 显然 \(dp[j]=max(dp[j],dp[i]+j-i)\) 显然我们只需要维护最大的 \(dp[i]-i\) 即可,这个显然可以用平衡树。反之,\(dp[j]=max(dp[j],dp[i])\) 这个可以暴力维护。

代码给出FHQ平衡数的写法:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+100;
int n,a[N],cnt,sum,ans,dp[N],root;
struct node{
	int val,key,ls,rs,ts,mx;
}tree[N];
int nn(int x,int y)
{
	tree[++cnt].key=rand();
	tree[cnt].val=x;
	tree[cnt].mx=tree[cnt].ts=y;
	return cnt;
}
void update(int x)
{
	tree[x].mx=max(tree[tree[x].ls].mx,tree[tree[x].rs].mx);
	tree[x].mx=max(tree[x].mx,tree[x].ts);
	return;
}
void split(int now,int val,int &x,int &y)
{
	if(now==0)
	x=y=0;
	else
	{
		if(tree[now].val<=val)
		{
			x=now;
			split(tree[now].rs,val,tree[now].rs,y);
		}
		else
		{
			y=now;
			split(tree[now].ls,val,x,tree[now].ls);
		}
		update(now);
	}
	return;
}
int merge(int x,int y)
{
	if(x==0||y==0)
	return x+y;
	if(tree[x].key<tree[y].key)
	{
		tree[x].rs=merge(tree[x].rs,y);
		update(x);
		return x;
	}
	else
	{
		tree[y].ls=merge(x,tree[y].ls);
		update(y);
		return y;
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	tree[0].mx=-1e9;
	root=nn(0,0);
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum+=a[i];
		dp[i]=ans;
		int x,y;
		split(root,sum,x,y);
		dp[i]=max(dp[i],i+tree[x].mx);
		root=merge(merge(x,nn(sum,dp[i]-i)),y);
		ans=max(ans,dp[i]);
	}
	cout<<dp[n];
	return 0;
}

标签:851,int,sum,tree,cin,Div,mx,dp,CFVP
From: https://www.cnblogs.com/MSjoker123/p/17659472.html

相关文章

  • 【LGR-153-Div.2】梦熊联盟 8 月月赛 Ⅳ & Cfz Round 1 & 飞熊杯 #1
    【LGR-153-Div.2】梦熊联盟8月月赛Ⅳ&CfzRound1&飞熊杯#1\(T1\)「CfzRound1」DeadCells\(100pts\)正解:模拟(注意特判)llgcd(lla,llb){ returnb?gcd(b,a%b):a;}intmain(){ lla,b,k,d,i,ans=1; a=read();b=read();k=read(); d=a/gcd(a,b)*b; f......
  • Codeforces Round 894 (Div. 3) ABCDEFG AK
    CodeforcesRound894(Div.3)第一次div3ak,虽然是vp的,后三题质量不错A-GiftCarpet穷举四个不同列即可,时间复杂度\(O(M^4)\)inta[100][100];voidsolve(){memset(a,0,sizeofa);intn,m;cin>>n>>m;for(inti=1;i<=n;i++)......
  • Codeforces Round 894 (Div. 3)
    CodeforcesRound894(Div.3)因为最近开学了,所以晚上可能就没有什么时间打这个了,不过以后一定会在第二天把题给补掉A题传送门A题意:就是在一个n*m的的字符矩阵中从左往右依次取出4列,使得每列包含vika这四个字符中按顺序出现一个。必须保证是按顺序出现。A思路:这是一个简......
  • 字体大小自动适应DIV--亲自测试有效-tomcat
    <!DOCTYPEhtml><html><head><title>phone设计</title><metacontent="text/html;charset=utf-8"http-equiv="Content-Type"/></head><body><divstyle="......
  • Codeforces Round 894 (Div. 3) A-F题解
    A.GiftCarpet题意最近,特马和维卡庆祝了家庭日。他们的朋友Arina送给他们一块地毯,这块地毯可以用拉丁文小写字母的\(n\cdotm\)表来表示。维卡还没看过礼物,但特马知道她喜欢什么样的地毯。如果维卡能在地毯上读出自己的名字,她一定会喜欢的。她从左到右逐列阅读,并从当前列中......
  • JS 拖动DIV边框改变其大小
    效果如下图所示:详细代码如下:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><style>body,html{width:100%;heig......
  • Codeforces Round #849 (Div. 4) 题解
    第一次打$\text{Div.4}$,感觉体验还行,差一题AK。##A直接使用if语句判断某个字符是否在字符串$\text{codeforces}$中出现过,幼儿园小朋友都会做。时间复杂度$\mathcal{O}(T)$,空间复杂度$\text{O}(1)$。ACCode##B用两个变量$x,y$记录当前走到哪里。若出现过$x=1,y=1$的......
  • Educational Codeforces Round 109 (Rated for Div. 2)
    B题没想到被坑了两次,极端情况明明也很好想,硬是WA了两发。C题很想之前做过的经典蚂蚁题,但是又不太一样,但分析之后,发现之后奇偶性相同才可能碰撞,那么分开处理,假如已经有相向而行,肯定是最快碰撞的,用一个栈维护即可,最后就是剩下的肯定是LLL...RRR将它们配对即可。#inclu......
  • div + css 详解
    第1页《Div+CSS布局大全》整理者:JesseZhao网站:送给我最爱的女朋友蜜蜜,希望她可以永远快乐幸福!!!《Div+CSS布局大全》第2页目录div+css布局入门..............................................................................................................
  • 【刷题笔记】29. Divide Two Integers
    题目Giventwointegers dividend and divisor,dividetwointegerswithoutusingmultiplication,divisionandmodoperator.Returnthequotientafterdividing dividend by divisor.Theintegerdivisionshouldtruncatetowardzero.Example1:Input:dividen......