首页 > 其他分享 >P11037 【MX-X3-T4】「RiOI-4」上课

P11037 【MX-X3-T4】「RiOI-4」上课

时间:2024-09-13 16:52:08浏览次数:1  
标签:方差 int T4 overline P11037 X3 Sigma sum MOD

P11037 【MX-X3-T4】「RiOI-4」上课

本文主要解释不断 \(+1\) 的过程如何快速实现的具体流程。

题意

给定正整数 \(n,q\) 和 \(n\) 个区间 \([l_i,r_i]\)。

有 \(q\) 组询问,每次询问给定一个整数 \(x\)。在每个区间内选择一个整数 \(a_i\)(\(l_i\leq a_i\leq r_i\)),使得所选整数的总和等于 \(x\),并使得选出的 \(a\) 序列的方差最小。输出方差最小值,对 \(998\,244\,353\) 取模。保证存在至少一种合法的选取方案。

输入格式

第一行两个正整数 \(n,q\)。

接下来的 \(n\) 行,每行两个自然数 \(l_i,r_i\)。

最后 \(q\) 行,每行一个整数 \(x\),表示一次询问。保证存在至少一种合法的选取方案。

输出格式

\(q\) 行,每行一个整数,表示最小方差对 \(998\,244\,353\) 取模的值。

样例 #1

样例输入 #1

3 3
1 3
2 3
3 5
6
9
11

样例输出 #1

665496236
0
554580197

样例 #2

样例输入 #2

4 3
1 4
11 12
3 9
6 10
21
29
26

样例输出 #2

811073551
811073543
748683272

提示

【样例解释 #1】

询问一方差最小的选择方案为 \({1,2,3}\),最小方差为 \(\frac{2}{3}\),有 \(665\,496\,236\times3\equiv 2\pmod{998\,244\,353}\),故输出 \(665\,496\,236\)。

询问二方差最小的选择方案为 \({3,3,3}\),最小方差为 \(0\),有 \(0\times1\equiv 0\pmod {998\,244\,353}\),故输出 \(0\)。

询问三方差最小的选择方案为 \({3,3,5}\),最小方差为 \(\frac{8}{9}\),有 \(554\,580\,197\times9\equiv 8\pmod{998\,244\,353}\),故输出 \(554\,580\,197\)。

【数据范围】

本题开启捆绑测试。

子任务 分数 \(n\) \(q\) 特殊性质
\(1\) \(9\) \(\le5\) \(\le5\) \(r_i\le5\)
\(2\) \(13\) \(\le2\times10^3\) \(\le2\times10^3\) \(r_i\le2\times10^3\)
\(3\) \(16\) \(\le10^6\) \(=1\)
\(4\) \(25\) \(\le10^5\) \(\le10^5\) \(r_i\le10^5\)
\(5\) \(37\) \(\le10^6\) \(\le10^6\)

对于所有数据,满足 \(1\leq n,q\leq 10^6\),\(0\leq l_i\leq r_i\leq 10^{6}\),对于每个 \(x\) 保证存在一种合法的方案。

核心

最重要的一个式子,有点类似于高中时学回归方程的时候学过的 \(\frac{\Sigma(x_i-\overline{x_i})^2}{\Sigma(y^2_i-\overline{y_i})^2}\),其中 \({\Sigma(x_i-\overline{x})^2}=\Sigma{x_i^2}-2\Sigma x_i\cdot{\overline x}+n\cdot \overline{x}^2=\Sigma{x_i^2}-2n\cdot \overline{x}^2+n\cdot \overline{x}^2\),也就是 \(\Sigma{x_i^2}-n\cdot \overline{x}^2\) 。

所以本题中的方差可以变成 \(\frac{\Sigma x_i^2}{n}-\overline x^2\) ,对于每一个询问的 \(\overline x^2\) 是固定的,所以要最小化的就是平方和 \(\Sigma x_i^2\) ,为了达到这个目的很显然的一个贪心就是让所有 \(a_i\) 取最小值 \(l_i\) ,设此时他们的和为 \(S_0\) ,那么我们还剩下 \(x-S_0\) 的数值要分配给这些 \(a_i\) ,那么只用把 \(x-S_0\) 依次分配给最小的 \(a_i\) 即可。

注意这里可能有理解上的偏差,并不能在排序过后按照 \(l_1,l_2...l_n\) 的顺序依次将他们变成 \(r_1,r_2...r_n\) ,直到不能操作为止,因为每次 \(+1\) 之后最小值都有可能变化;而是取出每次给最小值 \(a_{min}\) 加上 \(1\) 之后的序列中的最小值 \(a'_{min}\) 循环地动态进行该操作,否则你就只能在 \(subtask1\) 上 AC 两个点。

按照该过程手玩一下样例就会发现这实际上类似于一个倒水的过程,拿样例一举个例子的话(红线为初始值),可以具象为如下模型:

1

现在如果倒水进去,把最高液面的高度变为 \(4\) ,也就相当于对 \(a_i\) 们进行若干次操作后使得 \(\max a_i=4\),就会变成这样 :

2

其中我们花费的代价为 \(4\) ,也就是 \(4\) 个红格子。

那在这个问题中,我们一共需要花费的代价是 \(x-S_0\) ,很显然的是这个最后的最高高度是具有单调性的,也就是说总是存在一个 \(h\) ,使得在花费完 \(x-S_0\) 的代价后,最高液面 (最大的 \(a_i\) )能够达到 \(h\) ,但无法达到 \(h+1\) 。(注意最高一层的液面不一定都能恰好取到最大值,因为“液面”高度是用整数而不是小数来衡量的,比如下图这种 \(x-S_0=5\) 的情况) ,所以可以采取二分。

3

至于在二分内部的判断方式,我们可以定义一个 \(sum[h]\) 数组,表示将所有 \(l_i\) 提高到 \(\min{(h,r_i)}\) 的代价,可以想到维护 \(sum[h]\) 数组的方式就是根据 \([l_i,r_i]\) 依次在 \(sum[h]\) 内进行区间内每个数 \(+1\) 的操作 ,最后算出每个位置对应的值,再前缀和即可,可以在读入的时候就维护差分数组,再做两次前缀和的方式实现,不会的话请移步 P2367 。

统计答案

显然是不能够暴力枚举的,思考一下发现,如果我们现在算出了最大高度为 \(h\) :

​ 对于 \(r_i<h\) 的所有(显而易见,不可取等)区间 :其对应的 \(a_i\) 必取 \(r_i\) ,对答案的贡献为 \(r_i^2\) 。

​ 对于 \(h\le l_i\) 的所有(显而易见,可以取等)区间:其对应的 \(a_i\) 必取 \(l_i\) ,贡献为 \(l_i^2\) 。

​ 对于其他的所有区间:

​ 其 \(a_i\) 的可能取值为 \(h\) 或 \(h-1\) ,有 \(sum[h]-(x-S_0)\) 个 \(h-1\) , \((x-S_0)-sum[h-1]\) 个 \(h\),可以 \(O(1)\) 地统计。

前两种情况可以定义 \(Rans[h]\) 为高度为 \(h\) 时,\(\Sigma_i^{r_i<h} r_i^2\) ; \(Lans[h]\) 亦是如此。

由于一个 \(r_i\) 可以对所有比它大的高度产生贡献,符合区间加的特性,所以同样可以用差分的方式预处理求出。

小细节

涉及到逆元的最好开个 \(longlong\) ,尤其是在模数比较大的情况下,任何可能会爆的地方最好都取个模。

然后由于 \(sum,Lans,Rans\) 的下标都对应的是高度而不是编号 ,所以枚举的时候应该是从 \(L_{min}\) 到 \(R_{max}\)

Code

代码仅供参考,有些小地方的实现可能不同,不过不影响。

#include<bits/stdc++.h>
#define int long long
#define rr register 
using namespace std;
const int MOD=998244353;
template<typename T>inline void re(T &x)
{
	x=0;
	int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
}
template<typename T>inline void wr(T x)
{
	if(x>9)wr(x/10);
	putchar(x%10^48); 
}
inline int power(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%MOD;
		a=a*a%MOD;
		b/=2;
	}
	return ans%MOD;
}
const int N=1e6+10;
pair<int,int> q[N];
int sum[N],lsum[N],rsum[N],lcnt[N],rcnt[N];
int L=1e6+10,R=-1;
int n,tn,Q,S;
inline void add(int l,int r)
{
	sum[l]++,sum[r]--;
 } 
inline void pre()
{
	re(n),re(Q);	
	//sum
	for(rr int i=1;i<=n;++i)
				re(q[i].first),re(q[i].second),add(q[i].first,q[i].second),L=min(L,q[i].first),R=max(R,q[i].second),S+=q[i].first;		
	for(rr int i=L;i<=R;++i)sum[i]=sum[i-1]+sum[i];
	for(rr int i=L;i<=R;++i)sum[i]=sum[i-1]+sum[i];
	//cnt&sum_ans
	int l,r,tmp;
	for(rr int i=1;i<=n;++i)
	{
		l=q[i].first,r=q[i].second;
		rcnt[r+1]++,rcnt[R+1]--;
		lcnt[L]++,lcnt[l+1]--;
		tmp=l*l%MOD,lsum[L]=(lsum[L]+tmp)%MOD,lsum[l+1]=(lsum[l+1]-tmp+MOD)%MOD;
		tmp=r*r%MOD,rsum[r+1]=(rsum[r+1]+tmp)%MOD,rsum[R+1]=(rsum[R+1]-tmp+MOD)%MOD;
	}
	for(rr int i=L;i<=R;++i)
	{
		lcnt[i]+=lcnt[i-1],rcnt[i]+=rcnt[i-1];
		lsum[i]+=lsum[i-1],lsum[i]%=MOD;
		rsum[i]+=rsum[i-1],rsum[i]%=MOD;
	}
	//n^(-1)	
	tn=power(n,MOD-2);
}
//第一个大于等于 
inline int find(int x,int l,int r)
{
	if(l>=r)return l;
	int mid=(l+r)/2;
	if(sum[mid-1]>=x)return find(x,l,mid);
	else return find(x,mid+1,r);
}
inline int solve(int x)
{
	int ans1,ans2;
	int h=find(x-S,L,R);
	int res=n-rcnt[h]-lcnt[h],cnt=sum[h-1]-x+S;
	ans1=(rsum[h]+lsum[h])%MOD,ans1+=(h-1)*(h-1)%MOD*cnt%MOD+h*h%MOD*(res-cnt)%MOD,ans1=ans1%MOD*tn%MOD;
	ans2=(MOD-power(x%MOD,2)*power(tn,2)%MOD)%MOD;
	return (ans1+ans2)%MOD;
}
signed main()
{
	pre();
	int x;
	while(Q--)
	{
		re(x);
		wr(solve(x)),putchar('\n');
	}
	return 0;
}

标签:方差,int,T4,overline,P11037,X3,Sigma,sum,MOD
From: https://www.cnblogs.com/Hanggoash/p/18412512

相关文章

  • UDS 诊断 - RequestUpload(请求上传)(0x35)服务
    UDS诊断服务系列文章目录诊断和通信管理功能单元UDS诊断-DiagnosticSessionControl(诊断会话控制)(0x10)服务UDS诊断-ECUReset(ECU重置)(0x11)服务UDS诊断-SecurityAccess(安全访问)(0x27)服务UDS诊断-CommunicationControl(通信控制)(0x28)服务UDS诊断-TesterPresent......
  • UDS 诊断 - TransferData(传输数据)(0x36)服务
    UDS诊断服务系列文章目录诊断和通信管理功能单元UDS诊断-DiagnosticSessionControl(诊断会话控制)(0x10)服务UDS诊断-ECUReset(ECU重置)(0x11)服务UDS诊断-SecurityAccess(安全访问)(0x27)服务UDS诊断-CommunicationControl(通信控制)(0x28)服务UDS诊断-TesterPresent......
  • 京东h5st4.7.4(9段) 价值1000元?纯算奶妈级教学
    网站:aHR0cHM6Ly93d3cuamQuY29tLw==接口:aHR0cHM6Ly9hcGkubS5qZC5jb20=0.闲聊京东的h5st看着吓人一打开f12就显示本页面由京东-主站前端团队开发维护           --JDC其实过程很明显,经过了6,7个平坦流才可以拿到结果主要细心一点,相信你一定也......
  • P11036 【MX-X3-T3】「RiOI-4」GCD 与 LCM 问题
    P11036【MX-X3-T3】「RiOI-4」GCD与LCM问题题意描述给出\(a\),求一组构造\(b,c,d\)使得\(a+b+c+d=gcd(a,b)+lcm(c,d)\)同时需要保证\(b,c,d\le1634826193\)思路变量实在太多了,考虑先大胆消掉一个,令\(b=1\),此时问题简化为使得\(a+c+d=lcm(c,d)\)赛时真的没想出......
  • Tensorflow第T4周:猴痘病识别
    目录Tensorflow第T4周:猴痘病识别一、前期处理1、设置GPU2、导入数据3、查看数据二、数据预处理1.加载数据2.可视化数据3.再次检查数据4.配置数据集三、构建CNN网络四、编译五、训练模型六、模型评估1.Loss与Accuracy图2.指定图片进行预测Tensorflow第T4周:猴痘病识别......
  • C++竞赛初阶L1-15-第六单元-多维数组(34~35课)556: T456506 矩阵转置
    题目内容输入一个 n 行 m 列的矩阵 A,输出它的转置 AT。输入格式第一行包含两个整数 n 和 m,表示矩阵 A 的行数和列数。1≤n≤100,1≤m≤100。接下来 n 行,每行 m 个整数,表示矩阵 A 的元素。相邻两个整数之间用单个空格隔开,每个元素均在 1∼1000 之间。输......
  • C++竞赛初阶L1-15-第六单元-多维数组(34~35课)557: T456507 图像旋转
    题目内容输入一个 n 行 m 列的黑白图像,将它顺时针旋转 90 度后输出。输入格式第一行包含两个整数 n 和 m,表示图像包含像素点的行数和列数。1≤n≤100,1≤m≤100。接下来 n 行,每行 m 个整数,表示图像的每个像素点灰度。相邻两个整数之间用单个空格隔开,每个元素......
  • C++竞赛初阶L1-15-第六单元-多维数组(34~35课)555: T456505 矩阵乘法
    题目内容计算两个矩阵的乘法。n×m 阶的矩阵 A 乘以 m×k 阶的矩阵 B 得到的矩阵 C 是 n×k 阶的,且 C[i][j]=A[i][0]×B[0][j]+A[i][1]×B[1][j]+ …… +A[i][m−1]×B[m−1][j](C[i][j] 表示 C 矩阵中第 i 行第 j 列元素)。输入格式第一行为 n,m,k,表......
  • C++竞赛初阶L1-15-第六单元-多维数组(34~35课)554: T456504 矩阵加法
    题目内容输入两个 n 行 m 列的矩阵 A 和 B,输出它们的和 A+B,矩阵加法的规则是两个矩阵中对应位置的值进行加和,具体参照样例。输入格式第一行包含两个整数 n 和 m,表示矩阵的行数和列数 (1≤n≤100,1≤m≤100)。接下来 n 行,每行 m 个整数,表示矩阵 A 的元素......
  • 102MB缓存的锐龙5 7600X3D性能惊人!Zen5全都败了
    9月8日消息,AMD日前发布了锐龙57600X3D,是第一款AM5平台的六核心X3D产品,依然基于Zen4架构,配备多达102MB三级缓存,包括6MB二级缓存、32MB三级缓存、64MB3D缓存,热设计功耗仅为65W。不过,它没有公开零售,而是仅限欧美部分零售商,包括美国的MicroCenter、德国的MindFactory,后续是否会开放......