首页 > 其他分享 >2024暑假集训测试20

2024暑假集训测试20

时间:2024-08-09 15:54:32浏览次数:18  
标签:write 20 int void Tp 2024 inline 集训 dis

前言

状态不太好,又犯了老毛病死磕 T1,但 T1 是个很典的套路题我根本没听说过,T2 做过原题但没打。

T1 九次九日久重色

详细记录一下这个经典套路。

求最长上升子序列

\(O(n^2)\) 的就不写了,但是记录路径或方案书必须用 \(O(n^2)\),这里说如何 \(O(n\log n)\) 求。

因为这里只关注序列长度不关注具体元素,记录当前最长上升子序列的长度 \(len\) 与元素 \(f_i\),添加新的 \(a_i\) 时,若 \(a_i>f_{len}\) 则直接加入,否则二分找到第一个大于等于 \(a_i\) 的位置将其替换为 \(a_i\),从贪心的角度,在序列长度不变且满足单调的同时使其内部元素尽可能小从而方便填入后续元素。

对于两个排列求最长公共子序列

\(O(n^2)\) 的就不写了,但是记录路径或方案数必须用 \(O(n^2)\)。

最长公共子序列是可以转换为最长上升子序列的,对于数组 \(b\) 中元素在数组 \(a\) 中有对应位置,记录其为 \(c\) 数组,因为最长公共子序列是一个满足数组 \(a,b\) 下标均递增的二维偏序,所以 \(c\) 的最长上升子序列即为所求。

对于任意数量元素的两个序列求最长公共子序列

总体处理依然与上面类似,但是发现 \(b\) 数组中一个元素对应多个 \(a\) 数组元素,这几个是不能重复计算的,依然是一个二维偏序,考虑前面求的是最长上升子序列,那么只需要讲一个 \(b_i\) 对应 \(a\) 数组的几个位置递减排序放到 \(c\) 数组里,然后直接求就可以了,依然直接二分即可,不需要树状数组。

对于本题

等同于对于任意数量元素的两个序列求最长公共子序列,只是这里相等变成了整除,依然是对应若干个位置,预处理时对于 \(b_i\) 是从 \(1\) 循环到 \(\sqrt{b_i}\) 的,鉴于学习莫反时推的结论,\(\sqrt 1+\sqrt 2+\sqrt 3+…+\sqrt{n}≈\dfrac{2}{3}n\sqrt n\),再通过调和级数,\(c\) 数组的长度约为 \(n\log n\),所以最终复杂度为 \(O(\dfrac{2}{3}n\sqrt n+n\log^2 n)\)。

点击查看代码
#include<bits/stdc++.h>
#define ll long long 
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2e5+10,M=4e6+10;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
	for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x)
{if(x>9)wt(x/10);putchar((x%10)+'0');}
template<typename Tp> inline void write(Tp x)
{if(x<0)putchar('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar(' ');write(y...);}
int n,a[N],b[N],pos[N],c[M],tot,top,sta[N],f[N],len;
signed main()
{
	read(n);
	for(int i=1;i<=n;i++) 
	{
		read(a[i]);
		pos[a[i]]=i;
	}
	for(int i=1;i<=n;i++)
	{
		read(b[i]);
		top=0;
		for(int j=1;j*j<=b[i];j++)
			if(b[i]%j==0)
			{
				if(j*j==b[i]) sta[++top]=pos[j];
				else
				{
					sta[++top]=pos[j];
					sta[++top]=pos[b[i]/j];
				}
			}
		sort(sta+1,sta+1+top);
		while(top) 
		{
			c[++tot]=sta[top];
			top--;
		}
	} 
	f[1]=c[1],len=1;
	for(int i=2;i<=tot;i++)
	{
		if(c[i]>f[len]) f[++len]=c[i];
		else
		{
			int k=lower_bound(f+1,f+1+len,c[i])-f;
			f[k]=min(f[k],c[i]);
		}
	}
	write(len);
}

T2 天色天歌天籁音

把题读明白就做完了,贪心角度每次放入一个尽可能长的递增序列前产生 \(-1\) 的贡献,所以最终答案就是区间众数出现的次数 \(\times -1\)。

对此有很多写法,P4168 [Violet] 蒲公英 这题的在线分块做法复杂度在此题是错误的,因为没有要求在线,考虑使用莫队。

  • 回滚莫队,这个很显然直接写不删除莫队即可,与下面算法比优势是能够同时处理众数是谁,缺点是常数巨大。
  • 普通莫队,因为只询问次数不询问具体是谁,考虑删除一个元素时答案最多 \(-1\),所以先开一个桶,再给桶开一个桶就可以了。

复杂度均为 \(O(m\sqrt n)\)。

点击查看代码
#include<bits/stdc++.h>
#define ll long long 
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2e5+10;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
	for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x)
{if(x>9)wt(x/10);putchar((x%10)+'0');}
template<typename Tp> inline void write(Tp x)
{if(x<0)putchar('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar(' ');write(y...);}
int n,m,t,ans,a[N],b[N],pos[N],anss[N],cnt[N],sum[N];
struct aa {int l,r,id;}e[N];
bool cmp(aa a,aa b) {return pos[a.l]==pos[b.l]?((pos[a.l]&1)?a.r<b.r:a.r>b.r):a.l<b.l;}
void add(int x)
{
	sum[cnt[x]]--; cnt[x]++; sum[cnt[x]]++;
	ans=max(ans,cnt[x]);
}
void del(int x) 
{
	sum[cnt[x]]--; 
	ans-=(ans==cnt[x]&&sum[cnt[x]]==0);
	cnt[x]--; sum[cnt[x]]++;
}
signed main()
{
	read(n,m);
	t=sqrt(n);
	for(int i=1;i<=n;i++)
	{
		read(a[i]); b[i]=a[i];
		pos[i]=(i-1)/t+1;
	}
	sort(b+1,b+1+n);
	b[0]=unique(b+1,b+1+n)-(b+1);
	for(int i=1;i<=n;i++) 
		a[i]=lower_bound(b+1,b+1+b[0],a[i])-b;
	for(int i=1,l,r;i<=m;i++)
	{
		read(l,r);
		e[i]={l,r,i};
	}
	sort(e+1,e+1+m,cmp);
	for(int i=1,l=1,r=0;i<=m;i++)
	{
		while(l<e[i].l) {del(a[l]);l++;}
		while(l>e[i].l) {l--;add(a[l]);}
		while(r<e[i].r) {r++,add(a[r]);}
		while(r>e[i].r) {del(a[r]),r--;}
		anss[e[i].id]=ans;
	}
	for(int i=1;i<=m;i++) write(-anss[i]),puts("");
}

T3 春色春恋春熙风

据说是树上启发式合并发明者专门出的题,为此还专门学了一下树上启发式合并。

具体操作就是先遍历所有轻儿子,记录答案但不统计贡献;再遍历重儿子,记录答案饼统计贡献;最后遍历所有轻儿子,记录答案并统计贡献;当然别忘了自身节点贡献。

这么做正确性是显然的,复杂度分析详见 oi-wiki

因为只有 \(22\) 个边权,考虑状压,发现其为合法需满足二进制状态中重最多存在一个 \(1\),由此发现可以用路径异或和维护,利用边权的树上差分,\(dis(x,y)=dis(x,1)\bigoplus dis(lca,1)\bigoplus dis(y,1)\bigoplus dis(lca,1)=dis(x,1)\bigoplus dis(y,1)\)。

目标找到最长的一条链满足 \(dis(x,y)\) 合法,\(f_i\) 表示满足 \(dis(x,1)=i\) 中最大的 \(dep_x\);设 \(s\) 表示一种合法状态,有 \(dis(x,1)\bigoplus dis(y,1)=s\),即 \(dis(x,1)\bigoplus s=dis(y,1)\),再通过上面维护的 \(f\) 数组,用 \(len(x,y)=dep_x+dep_y-2dep_{lca}\) 求解即可。

复杂度 \(O(22n\log n)\)。

点击查看代码
#include<bits/stdc++.h>
#define ll long long 
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5e5+10,M=5e6+10;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
	for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x)
{if(x>9)wt(x/10);putchar((x%10)+'0');}
template<typename Tp> inline void write(Tp x)
{if(x<0)putchar('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar(' ');write(y...);}
int n,tot,a[N],sz[N],son[N],in[N],out[N],pos[N],f[M],ans[N],sum[N],dep[N];
vector<int>e[N];
void add1(int x,int y)
{
	ans[x]=max(ans[x],dep[y]+f[sum[y]]-(dep[x]<<1));
	for(int i=0;i<=21;i++) 
		ans[x]=max(ans[x],dep[y]+f[sum[y]^(1<<i)]-(dep[x]<<1));
}
void add2(int x) {f[sum[x]]=max(f[sum[x]],dep[x]);}
void dfs1(int x,int fa)
{
	in[x]=++tot; pos[tot]=x; sz[x]=1; dep[x]=dep[fa]+1;
	sum[x]=(x!=1)*(sum[fa]^(1<<a[x]));
	for(int y:e[x])
	{
		dfs1(y,x);
		sz[x]+=sz[y];
		son[x]=sz[son[x]]<sz[y]?y:son[x];
	}
	out[x]=tot;
}
void dfs2(int x,int fa,bool flag)
{
	for(int y:e[x]) if(y!=son[x]) dfs2(y,x,0);
	if(son[x]) dfs2(son[x],x,1);
	for(int y:e[x])
		if(y!=son[x])
		{
			for(int i=in[y];i<=out[y];i++) add1(x,pos[i]);
			for(int i=in[y];i<=out[y];i++) add2(pos[i]);
		}
	add1(x,x),add2(x);
	for(int y:e[x]) ans[x]=max(ans[x],ans[y]);
	if(!flag)
		for(int i=in[x];i<=out[x];i++) f[sum[pos[i]]]=-0x3f3f3f3f;
}
signed main()
{
	read(n);
	char s;
	for(int i=2,x;i<=n;i++)
	{
		read(x); cin>>s; 
		a[i]=s-'a';
		e[x].push_back(i);
	}
	memset(f,-0x3f,sizeof(f));
	dfs1(1,0); dfs2(1,0,1);
	for(int i=1;i<=n;i++) write(ans[i]),putchar(' ');
}

T4 雪色雪花雪余痕

不会。

总结

有的东西积蓄依旧早晚要写,不然会憋坏的,本想找个最不开心的一天,打得这么唐正是好时候吧,但昨天忙着改题没时间,今天好不容易没有模拟赛不想扰了好心情,也许 hz 最好的抑制情绪的手段就是让人忙得没时间沮丧吧……

标签:write,20,int,void,Tp,2024,inline,集训,dis
From: https://www.cnblogs.com/Charlieljk/p/18350891

相关文章

  • 2024黑客从零基础入门到精通(超详细),看完这一篇就够了
    首先要明白啊,我们现在说的黑客不是那种窃取别人信息、攻击别人系统的黑客,说的是调试和分析计算机安全系统的网络安全工程师。黑客技术的核心就是渗透攻防技术,是为了证明网络防御按照预期计划正常运行而提供的一种机制。就是通过模拟恶意黑客的攻击方法,来评估计算机网络系统......
  • 2024暑假集训测试19
    前言比赛链接。T1因为忘记判一个东西挂分,听说还有被卡哈希的,题目若按照难度正序的话应该是T2、T1、T4、T3,T4看到图论就比较胆怯没怎么想,T3当然没想出来。总而言之T1挂分的人挺多的,T2都能做出来,T1不挂分的排名都很靠前。打得……不算很唐吧,除了T1挂分。T1串串......
  • 2024.8 #5 午夜时分月上枝头 谁为谁心疼 一杯浊酒浇在心头 谁让谁心冷
    午夜时分月上枝头谁为谁心疼一杯浊酒浇在心头谁让谁心冷----洛天依《广寒宫》1.ChoosingAds考虑最简单的情况,即\(p>50\)。那么这个问题就是请问出现次数\(>\dfrac{n}{2}\)的数。Lemma:我们每次随机删除不相等的两个数,那么留下来的那个(那些)数就是答案。Proof:假如......
  • 福昕高级PDF编辑器专业版 v2024 激活版
    福昕高级PDF编辑器是一款功能强大的PDF文件编辑软件,提供多种实用的编辑功能。软件功能:PDF文档编辑:用户可编辑PDF文档内容,包括文字、图片、表格、图形等,且不会对原有文本内容造成影响。批注工具:提供多种批注工具,如注释,连线框和浮动注释,在PDF文件中添加批注和标记以便于阅读。......
  • AD20如何批量修改丝印的大小
    选择想修改的元器件丝印,右击以下鼠标,出现如下界面在ObjectSpecifics里面选择Designgnator,将Any选项选择为same然后再右侧修改丝印的高和宽,一般将高选择为10mil,宽选择为2个mil。PS:一般推荐字宽/字高尺寸为2/10mil、4/25mil、5/30mil、6/45mil。......
  • AD20如何批量放置过控
    依此点击工具、(缝合孔)栅格一般放150个mil。然后选择层、GND网络。注意//需要铺完铜才能继续操作。可以点击constrainarea按钮选项在自己规定的区域放置过孔,一般是24mil以及12mil。......
  • 派胜OA ExpressOA 3.0 现已支持 Windows Server 2022
    ExpressOA3.0跨平台,高性能,现代化的协同办公平台系统。派胜ExpressOA3.0现已支持WindowsServer2022。WindowsServer2022是微软推出的第九个WindowsServer系列操作系统。也是Windows10的第三个服务器版本。它的第一个早期预览版本于2021年3月2日发布,正式版已于同年8月19......
  • [十二省联考 2019] 异或粽子
    如果这道题目会可持久化trie的话,是可以用“超级钢琴”这一道题目的思路去做的如果不行的话,考虑用trie,然后这篇题解关于trie的常用trick的综合可以记住讲一下怎么查找第\(k\)大,不要用二分了,直接把\(sum_r\)放在trie树上查找。trie树每个点记录一下这个点的子树有多少个位置(这个维......
  • 【11月杭州,邀您投稿参会】2024年计算机视觉与图像处理国际学术会议 (CVIP 2024)
    【重要信息】会议官网:iccvip.org大会时间:2024年11月15日-17日大会地点:中国杭州一轮截稿日期:2024年8月21日接受/拒稿通知:投稿后1周内收录检索:EICompendex,Scopus【大会简介】2024年计算机视觉与图像处理国际学术会议(CVIP2024)将于2024年11月15日-17日在中国杭州举......
  • Leetcode | 202 Happy Number
    分析在快乐数的题意上,通常情况下我们都会去顺着题目的意思去寻找最终结果是否为1,而后面的另一句话很有启示意义:"也可能是无限循环,但始终变不到1",那么为什么不会是无限不循环呢?证明范围限制:对于一个(d)位数的正整数(n),其最大值为99d=Max位数减少:每次计算之后,数字位数d要么减......