暑假集训CSP提高模拟16

1.九次九日九重色

一开始做的时候被题面给迷惑住了,没想到可以跳着 匹配(样例太水)。
那我们来考虑如何做,首先思路肯定是把能匹配的暴力求出来,根据不知道怎么搞的调和计数,这样的复杂度还不是很高,是O(NlogN),可以搞。
观察一下预处理出来的序列,是不是很熟悉。没错剩下的就是求最长上升子序列。

那求最长上升子序列有两种方法,一个是O(n2)的DP,还有一个O(NlogN)的二分。
这里主要了解后面的(因为赛时我还不会)。
原理其实比较简单,看代码就能看懂。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int N=2e5+107;
int n,x[N],y[N];
int pos1[N],pos2[N];
struct lmy
{
	int x,y;
}s[N<<5];
bool comp(lmy a,lmy b)
{
	if(a.x==b.x) return a.y>b.y;
	return a.x<b.x;
}
int st[N<<5],top;
int cnt;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&x[i]),pos1[x[i]]=i;
	for(int i=1;i<=n;i++) scanf("%d",&y[i]),pos2[y[i]]=i;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j*x[i]<=n;j++)
		{
			s[++cnt]={pos1[x[i]],pos2[x[i]*j]};
		}
	}
	sort(s+1,s+1+cnt,comp);
	for(int i=1;i<=cnt;i++)
    {
        if(st[top]<s[i].y)
        {
            st[++top]=s[i].y;
        }
        else
        {
            st[lower_bound(st+1,st+top+1,s[i].y)-st]=s[i].y;
        }
    }
    printf("%d",top);
}

2.天色天歌天籁音

简单理解一下题意,再自己手模一下,可以发现题目所求的是区间众数,然后它强调了一下各个互不影响,可以考虑莫队(其实挺套路的,但我不会莫队了,大悲)。
主要讲讲add和del的操作,
首先add比较好说,只需要直接计数。

del就需要分讨一下。
1.减之前比目前最大众数小,无影响。
2.本身是最大众数,减完之后还是,无影响。
3.本身为最大众数(但众数有很多个),减之后不为最大众数(主要的问题)。

关于这个问题,我们就可以开一个桶来记录每个数出现个数(众数)的个数(是有点绕,得理解一下),到这这个题就没什么了

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int N=3e5+107;
int n,m,a[N];

int li[N],ri[N],bg[N],tot;
struct lmy
{
	int x,y,id;
}q[N];
bool comp(lmy &a,lmy &b)
{
	int p=bg[a.x],q=bg[b.x];
	if(p!=q) return p<q;
	if(p&1) return a.y<b.y;
	else return a.y>b.y;
}

void fk()
{
	int sq=sqrt(n);
	for(int i=1;i<=sq;i++)
	{
		li[i]=ri[i-1]+1;
		ri[i]=sq*i;
		if(i==sq) ri[i]=n;
		for(int j=li[i];j<=ri[i];j++) bg[j]=i;
	}
}


map<int,int> mp;

int sum,t[N],cnt[N],ans[N];
void add(int i)
{
	t[cnt[a[i]]]--;
	t[++cnt[a[i]]]++;
	sum=max(sum,cnt[a[i]]);
}

void del(int i)
{
	t[cnt[a[i]]]--;
	if(cnt[a[i]]==sum&&!t[cnt[a[i]]]) sum--;
	t[--cnt[a[i]]]++;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) 
	{
		scanf("%d",&a[i]);
		if(mp.find(a[i])==mp.end())
		{
			mp[a[i]]=++tot;
		}
		a[i]=mp[a[i]];
	}
	fk();
	for(int i=1;i<=m;i++)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		q[i]={l,r,i};
	}
	sort(q+1,q+1+m,comp);
	int l=1,r=0;
	for(int i=1;i<=m;i++)
	{
		while(r<q[i].y) add(++r);
		while(r>q[i].y) del(r--);
		while(l<q[i].x) del(l++);
		while(l>q[i].x) add(--l);
		ans[q[i].id]=sum;
	}
	for(int i=1;i<=m;i++) printf("%d\n",-ans[i]);
}
posted @   zhengchenxi  阅读(52)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示