首页 > 其他分享 >【题解】CPS-S模拟2

【题解】CPS-S模拟2

时间:2024-09-08 14:35:43浏览次数:8  
标签:lfloor return int 题解 long rfloor tfrac CPS 模拟

目录

Pre

image
赛时没有第一时间找到签到题,遂四处游走,后来决定先打T1,约1h时切了,然后1h打后3题暴力,后面推了推T4一个特殊性质,推了推T2一个特殊性质,但是T2的推假了。不太清楚怎么就来到了最后半小时,推T2的第二个特殊性质,未果,最后15min想到了T4的 \(O(n^2)\) 暴力但是没打完,算挂分吗。

T1.不相邻集合

题目描述

定义一个可重集合是不相邻集合当且仅当集合中任意两个数的差 \(\ge2\)。现在给你一个序列 \(a\),对于它的所有前缀求能组成的最大的不相邻集合的大小。

部分分

40pts

\(O(n^2)\) DP。设 \(dp[i][0]\) 表示以 \(i\) 值开头的最大不相邻集合的大小,\(dp[i][1]\) 表示以 \(i\) 值结尾的最大不相邻集合的大小,则有转移:

\[dp[i][0]=max\,dp[j][0](j\ge i+2) +1 \]

\[dp[i][1]=max\,dp[j][1](j\le i-2) +1 \]

注意 \(+1\) 一定要放在取max外面。

10pts

在所有 \(a_i\) 都是奇数的情况下,我们任选不重复的数它们的差都一定 \(\ge2\),去重后直接统计即可。

正解

思路

对40pts的暴力进行优化。首先,重复的元素绝对没有任何贡献,所以仿照10pts的处理,先去重,也就是如果有重复的数,直接输出旧有的答案,然后不进行任何处理。
发现复杂度瓶颈在转移,有 \(O(n)\) 的遍历取max。区间最大值使我们想到线段树,于是这个东西用两颗线段树维护,支持单点赋值、区间查找最大值,复杂度 \(O(n\log n)\)。

代码

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
int a,b[300003],mx,mn,num;
bool use[500005];
struct XDS
{
	#define N 2200022
	int left[N],right[N],num[N];
	il int lft(int x)
	{
		return x<<1;
	}
	il int iht(int x)
	{
		return x<<1|1;
	}
	il void pu(int x)
	{
		num[x]=max(num[lft(x)],num[iht(x)]);
	}
	void make(int x,int lt,int rt)
	{
		left[x]=lt;
		right[x]=rt;
		if(lt==rt)
		{
			num[x]=0;
			return;
		}
		ri me=(lt+rt)>>1;
		make(lft(x),lt,me);
		make(iht(x),me+1,rt);
		pu(x);
	}
	void add(int x,int pl,int y)
	{
		if(left[x]==right[x])
		{
			num[x]=y;
			return;
		}
		ri me=(left[x]+right[x])>>1;
		if(pl<=me)
		{
			add(lft(x),pl,y);
		}
		else
		{
			add(iht(x),pl,y);
		}
		pu(x);
	}
	int found(int x,int lt,int rt)
	{
		if(lt>rt)
		{
			return 0;
		}
		if(lt<=left[x]&&right[x]<=rt)
		{
			return num[x];
		}
		ri me=(left[x]+right[x])>>1,rn=-inf;
		if(lt<=me)
		{
			rn=max(rn,found(lft(x),lt,rt));
		}
		if(rt>me)
		{
			rn=max(rn,found(iht(x),lt,rt));
		}
		return rn;
	}
	#undef N
}tree[2];
int main()
{
	scanf("%d",&a);
	mx=-inf,mn=inf;
	for(ri i=1;i<=a;i++)
	{
		scanf("%d",&b[i]);
		mx=max(mx,b[i]);
		mn=min(mn,b[i]);
	}
	tree[0].make(1,1,mx);
	tree[1].make(1,1,mx);
	for(ri i=1;i<=a;i++)
	{
		if(use[b[i]])
		{
			printf("%d ",num);
			continue;
		}
		use[b[i]]=true;
		ri j=tree[0].found(1,b[i]+2,mx);
		tree[0].add(1,b[i],j+1);
		num=max(num,j+1);
		j=tree[1].found(1,mn,b[i]-2);
		tree[1].add(1,b[i],j+1);
		num=max(num,j+1);
		printf("%d ",num);
	}
	return 0;
}

T2.线段树

题目描述

void build(int i, int l, int r) {
    L[i] = l; R[i] = r;
    if (l == r) return;
    int mid = (l+r)/2;
    build(i*2, l, mid); build(i*2+1, mid+1, r);
}

以上面的代码运行一遍build(1,1,n),求 \(\sum\limits_{i\in[x,y]}i\),答案 \(\bmod 10^9+7\)。\(1\le x\le y\le n\le 10^{18}\)。

部分分

20pts

暴力建树,统计区间和,复杂度 \(O(n\log n)\)。

正解

思路

发现复杂度主要来源于建树,考虑省略这一步,也就是 \(O(1)\) 求解某点的权值。设 \(f()\) 表示在一定条件下以某位置为根的总贡献,首先可知这个东西只和区间长度 \(n\) 和根值 \(x\) 有关,所以设为 \(f(n,x)\)(因为 \(n\) 值定了,以其为根的树的形态就定了;此时很显然它的左右儿子的值可以用根值表示,而下面的后代又可以被其左右儿子的值表示,以此类推,只要 \(n,x\) 定了,\(f()\) 的值就定了)。
然后通过理性分析||打表找规律,发现当 \(n\) 值定了以后,\(f(n,x)\) 是关于 \(x\) 的一次函数。
image
这是初始树。
image
这是改变后的树。发现当根值 \(+a\),\(f(n,a)\)一定加的是 \(ka\),这时 \(f(n,x)\) 显然是一个一次函数,且这个 \(k\) 貌似只和树的形态有关系,也就是只和 \(n\) 有关系。\(x=0\) 时取到的\(b\)值同理,也只和 \(n\) 有关系。
设 \(f(n,x)=k_nx+b_n\),已知一个重要等式:

\[f(n,x)=f(\lceil{\tfrac{n}{2}}\rceil,2x)+f(\lfloor{\tfrac{n}{2}}\rfloor,2x+1)+x \]

左右两边同时展开,得:

\[k_nx+b_n=2k_{\lceil{\tfrac{n}{2}}\rceil}x+b_{\lceil{\tfrac{n}{2}}\rceil}+2k_{\lfloor{\tfrac{n}{2}}\rfloor}x+k_{\lfloor{\tfrac{n}{2}}\rfloor}+b{\lfloor{\tfrac{n}{2}}\rfloor}+x \]

合并同类项,得:

\[k_nx+b_n=(2k_{\lceil{\tfrac{n}{2}}\rceil}+2k_{\lfloor{\tfrac{n}{2}}\rfloor}+1)x+b_{\lceil{\tfrac{n}{2}}\rceil}+k_{\lfloor{\tfrac{n}{2}}\rfloor}+b{\lfloor{\tfrac{n}{2}}\rfloor} \]

由于是一次函数相同,所以 \(k,b\) 得分别相同,也就是:

\[\begin{cases}k_n=2k_{\lceil{\tfrac{n}{2}}\rceil}+2k_{\lfloor{\tfrac{n}{2}}\rfloor}+1\\b_n=b_{\lceil{\tfrac{n}{2}}\rceil}+k_{\lfloor{\tfrac{n}{2}}\rfloor}+b{\lfloor{\tfrac{n}{2}}\rfloor}\end{cases} \]

然后就可以使用记搜 \(O(\log n)\) 的复杂度内求解线段树上一个节点的贡献了。外层还是线段树的查询,只不过不建树,递归记录区间左右端点,找到合法区间直接原地统计答案,所以再带上外层线段树的 \(\log n\),总复杂度 \(O(T\log^2n)\)。

代码

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
int a;
const int mod=1e9+7;
long long b,c,d;
map<long long,long long>kk,bb;
il long long K(long long x)
{
	if(x==1)
	{
		return 1;
	}
	if(kk[x])
	{
		return kk[x];
	}
	kk[x]=((K(x>>1)<<1)+(K(((x+1)>>1))<<1)+1)%mod;
	return kk[x];
}
il long long B(long long x)
{
	if(x==1)
	{
		return 0;
	}
	if(bb[x])
	{
		return bb[x];
	}
	bb[x]=(B(x>>1)+B((x+1)>>1)+K(x>>1))%mod;
	return bb[x];
}
il long long got(long long x,long long y)
{
	return (K(x)*y+B(x))%mod;
}
long long found(long long x,long long lt,long long rt,long long left,long long right)
{
	if(lt<=left&&right<=rt)
	{
		return got(right-left+1,x);
	}
	register long long me=(left+right)>>1,rn=0;
	if(lt<=me)
	{
		rn+=found((x<<1)%mod,lt,rt,left,me);
		rn%=mod;
	}
	if(rt>me)
	{
		rn+=found((x<<1|1)%mod,lt,rt,me+1,right);
		rn%=mod;
	}
	return rn;
}
int main()
{
	scanf("%d",&a);
	while(a--)
	{
		scanf("%lld%lld%lld",&b,&c,&d);
		printf("%lld\n",found(1,c,d,1,b));
	}
	return 0;
}

T3.

部分分

40pts

正解

思路

代码

T4.

部分分

10pts

正解

思路

代码

And

标签:lfloor,return,int,题解,long,rfloor,tfrac,CPS,模拟
From: https://www.cnblogs.com/ywhhdjser-97/p/18402499

相关文章

  • [ABC370C] Word Ladder 题解
    题目描述:给予两个相等长度的序列,\(S\)与\(T\),以及一个空数组\(X\),每在\(S\)上修改一个字符,便将修改后的\(S\)加入\(X\)中,直到\(S\)与\(T\)相同。(输出字典序最小的\(X\)数组)拿过题一看,感觉还是蛮简单的,本题主要的难点在字符串的字典序上。字符串字典序的定义......
  • P11019 「LAOI-6」[太阳]] 请使用最新版手机 QQ 体验新功能 题解
    非常简单的模拟题。由题意得,即找出输入字符串中,用[]围起来的片段中的大写字母\(A_1,A_2,A_3...A_n\)然后将其转换为小写输出\(/a_1a_2a_3...a_n\)即可。#include<bits/stdc++.h>#defineseq(q,w,e)for(intq=w;q<=e;q++)#definelllonglongusingnamespace......
  • P11020 「LAOI-6」Radiation 题解
    一道简单的构造题,其实不用想的十分复杂的说。首先,最多发射的宇宙射线\(sum\)也最多为\(sum_{max}=min(m,n)\)也就是说,无论如何摆放石子,也只能达到这个数量。那么我们的目的便变成了如何让石子变成这一个形状。如上图,在一个\(3\times6\)的矩阵中,其实只要三颗石子即可满足......
  • AtCoder Beginner Contest 370 A-F题解
    A#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;mt19937rnd(time(0));#defineintlonglongtypedeftuple<int,int,int>tp;#definexfirst#defineysecondtypedefpair<int,int>pii;typedefpair<double,double>......
  • 【C++】vector的模拟实现
    文章目录一、前言二、构造函数模拟实现构造函数调用不明确1.问题描述2、解决调用不明确的方法三、基础接口1.empty和clear2.size和capacity3.[]和iterator四、resize和reservereserve中的深浅拷贝问题1、reserve中浅拷贝发生原因2、浅拷贝发生的图解3、解决方法五、尾......
  • 配置PHP的Session存储到Mysql / Redis / memcache 以及使用opcache以及apc缓存清除工
    一、配置PHP的Session存储到Mysql,Redis以及memcache等        PHP的会话默认是以文件的形式存在的,可以通过简单的配置到将Session存储到NoSQL中,即提高了访问速度,又能很好地实现会话共享!1.默认配置:session.save_handler=filessession.save_path=/tmp/2.配......
  • 【洛谷 P1996】约瑟夫问题 题解(队列+模拟+循环)
    约瑟夫问题题目描述个人围成一圈,从第一个人开始报数,数到的人出列,再由下一个人重新从开始报数,数到的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰名小朋友,而该题是全部出圈。输入......
  • 【题解】CF1955E
    CF1955E翻译思路代码翻译原题链接CF1955E思路  由于每次操作区间长度是定值,所以我们可以说,如果最前面的数已经是1了,那它再也不会被进入操作。因为如果把它变回0,那想再变成1只能以它为起点再操作一次,前后两次操作抵消。  所以思路很简单,直接......
  • Leetcode 第 409 场周赛题解
    Leetcode第409场周赛题解Leetcode第409场周赛题解题目1:3242.设计相邻元素求和服务思路代码复杂度分析题目2:3243.新增道路查询后的最短距离I思路代码复杂度分析题目3:3244.新增道路查询后的最短距离II思路代码复杂度分析题目4:3245.交替组III思路代码复杂度......
  • 大连市第二十四中学模拟飞行社团章程(草案)
    亲爱的飞行员:你好!欢迎来到大连市第二十四中学模拟飞行社团!我们致力于为每一位喜爱蓝天的同志提供不一样的模拟飞行体验。同时,为了是您更好的了解本社团并在加入后有更好的体验,我们特在此制作本社团章程,旨在维护社团有序、和谐的运行。一.社团简介本社团全名大连市第二十四中学......