NOIP模拟21:「Median·Game·Park」
T1:Median
  线性筛+桶+随机化(??什么鬼?)。
  首先,题解一句话秀到了我:
考虑输入如此诡异,其实可以看作随机数据
  随机数据??
  这就意味着分布均匀。。
  又考虑到w<=k<=n
  可以用桶了。
  中位数暴力算的话是排序后取中间。
  但是时间明显不允许。只能\(O(n)\)过掉。所以要维护两个中位数指针(k%2==1当然就是一个了)。
  由于数据随机,分布均匀,所以可以直接跳桶。
  笑死,我当时不信还把数据输了出去,发现有的相邻数据差了几百,就这还能直接跳。。。。。好吧,我肤浅了。。。。
  差点没调出来的代码:
200行的煌煌大作QWQ
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
	#define ll long long
	#define rr register
	const int N=1.1e7;
	const int MAXN=1.8e8+3;
	int n,k;
	int w;
	ll cnt,prime[N];
	bool notprime[MAXN];
	double ans;
	int s2[N];
	int ton[N<<1];
	inline void Prime()
	{
		for(rr int i=2;i<MAXN;i++)
		{
			if(!notprime[i]) prime[++cnt]=i;
			for(rr int j=1;j<=cnt&&i*prime[j]<MAXN;j++)
			{
				notprime[i*prime[j]]=1;
				if(!(i%prime[j]))
					break;
			}
		}
	}
	inline int read()
	{
		rr int x_read=0,y_read=1;
		rr char c_read=getchar();
		while(c_read<'0'||c_read>'9')
		{
			if(c_read=='-') y_read=-1;
			c_read=getchar();
		}
		while(c_read<='9'&&c_read>='0')
		{
			x_read=(x_read*10)+(c_read^48);
			c_read=getchar();
		}
		return x_read*y_read;
	}
};
using namespace STD;
int main()
{
	Prime();
	n=read(),k=read(),w=read();
	for(rr int i=1;i<=n;i++)
	{
		prime[i]=prime[i]*i%w;
		s2[i]=prime[i]+prime[i/10+1];
	}
	if(k&1)
	{
		int *p=ton+s2[1],l=1,sum=1;
		ton[s2[1]]++;
		for(rr int i=2;i<=k;i++)
		{
			sum++;
			ton[s2[i]]++;
			if(s2[i]<=(p-ton)) l++;
			if(l<((sum>>1)+1))
				while(l<((sum>>1)+1))
				{
					p++;
					while(!(*p)) p++;
					l+=(*p);
				}
			else
				while(l-(*p)>=((sum>>1)+1))
				{
					l-=(*p);
					p--;
					while(!(*p)) p--;
				}
		}
		ans+=(p-ton);
		for(rr int i=k+1;i<=n;i++)
		{
			ton[s2[i]]++;
			if(s2[i]<=p-ton) l++;
			ton[s2[i-k]]--;
			if(s2[i-k]<=p-ton) l--;
			if(l<((k>>1)+1))
				while(l<((k>>1)+1))
				{
					p++;
					while(!(*p)) p++;
					l+=(*p);
				}
			else
				while(l-(*p)>=((k>>1)+1))
				{
					l-=(*p);
					p--;
					while(!(*p)) p--;
				}
			ans+=(p-ton);
		}
		printf("%.1lf\n",ans);
	}
	else
	{
		int *p1=ton+min(s2[1],s2[2]),*p2=ton+max(s2[1],s2[2]),l2=2,l1=1,sum=2;
		ton[s2[1]]++;
		ton[s2[2]]++;
		for(rr int i=3;i<=k;i++)
		{
			sum++;
			ton[s2[i]]++;
			if(s2[i]<=(p1-ton)) l1++;
			if(s2[i]<=(p2-ton)) l2++;
			if(l2<((sum>>1)+1))
				while(l2<((sum>>1)+1))
				{
					p2++;
					while(!(*p2)) p2++;
					l2+=(*p2);
				}
			else
				while(l2-(*p2)>=((sum>>1)+1))
				{
					l2-=(*p2);
					p2--;
					while(!(*p2)) p2--;
				}
			if(l1<(sum>>1))
				while(l1<(sum>>1))
				{
					p1++;
					while(!(*p1)) p1++;
					l1+=(*p1);
				}
			else
				while(l1-(*p1)>=(sum>>1))
				{
					l1-=(*p1);
					p1--;
					while(!(*p1)) p1--;
				}
		}
		double temp=((p1-ton)+(p2-ton));
		ans+=(temp/2.00);
		for(rr int i=k+1;i<=n;i++)
		{
			ton[s2[i]]++;
			if(s2[i]<=(p1-ton)) l1++;
			if(s2[i]<=(p2-ton)) l2++;
			ton[s2[i-k]]--;
			if(s2[i-k]<=p1-ton) l1--;
			if(s2[i-k]<=p2-ton) l2--;
			if(l2<((k>>1)+1))
				while(l2<((k>>1)+1))
				{
					p2++;
					while(!(*p2)) p2++;
					l2+=(*p2);
				}
			else
				while(l2-(*p2)>=((k>>1)+1))
				{
					l2-=(*p2);
					p2--;
					while(!(*p2)) p2--;
				}
			if(l1<(k>>1))
				while(l1<(k>>1))
				{
					p1++;
					while(!(*p1)) p1++;
					l1+=(*p1);
				}
			else
				while(l1-(*p1)>=(k>>1))
				{
					l1-=(*p1);
					p1--;
					while(!(*p1)) p1--;
				}
			temp=(p1-ton)+(p2-ton);
			ans+=temp/2.00;
		}
		printf("%.1lf\n",ans);
	}
}
  其他的事情
  在讨论时土哥提到了一个叫”对顶堆”的东西来维护中位数,当然,\(O(nlogn)\)会TLE。
  这个东西其实就是维护两个堆,一个大根堆,一个小根堆。
  小根堆里的数全部大于大根堆里的数,这样就有单调性了,相当于排了个序。
  但比直接用排序算法在N上少了个指数。
  当有数进来时,先与两个堆顶比较如果大于大根堆顶就进小根堆,否则进大根堆。
  然后比较两个堆的大小,然后将多的数放进另一个堆即可。
  中位数就是堆顶之和除以2
  至于说k%2==1的情况,你就不要把中位数往堆里放即可。
T2:Game
  考场上一眼看出来就是贪心,直接放了个堆上去,还纳闷为啥这么简单呢。。
  然后T了。
  正解是\(O(nk)\)
  还是桶。一场考试三道题,两道考桶。。。。
  这题有个看起来很明显但是你往往会忽视的性质:
如果你拿进序列的数比当前序列里的最大值还要大,那么它下一轮一会被拿走
  简单到无需证明。。
  但是他会决定你是\(A\)还是\(T\)。
  记得开longlong。
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
	#define ll long long
	#define rr register
	#define inf INT_MAX
	const int N=100004;
	const int K=2004;
	int n,k,p;
	int *po;
	ll score[2];
	ll a[N];
	int b[N];
	int read()
	{
		rr int x_read=0,y_read=1;
		rr char c_read=getchar();
		while(c_read<'0'||c_read>'9')
		{
			if(c_read=='-') y_read=-1;
			c_read=getchar();
		}
		while(c_read<='9'&&c_read>='0')
		{
			x_read=(x_read*10)+(c_read^48);
			c_read=getchar();
		}
		return x_read*y_read;
	}
};
using namespace STD;
int main()
{
	n=read(),k=read();
	for(rr int i=1;i<=n;i++)
		a[i]=read();
	while(k--)
	{
		int p=read();
		ll temp=-inf;
		int roun=1;
		int now=p;
		for(rr int i=1;i<=p;i++)
		{
			temp=max(temp,a[i]);
			b[a[i]]++;
		}
		po=b+temp;
		temp=-inf;
		while(roun<=n)
		{
			if(temp>(po-b))
			{
				score[roun&1]+=temp;
				temp=-inf;
			}
			else
			{
				score[roun&1]+=(po-b);
				int x=*po;
				x--;
				*po=x;
			}
			now++;
			if(now<=n)
			{
				if(a[now]>(po-b))
					temp=a[now];
				else
					b[a[now]]++;
			}
			while(((*po)==0)&&(po>b))
				po--;
			roun++;
		}
		printf("%lld\n",score[1]-score[0]);
		score[0]=score[1]=0;
	}
}
T3:Park
还在推方程,先鸽掉好了。
NOIP模拟21:「Median·Game·Park」的更多相关文章
- NOIP 模拟 $21\; \rm Median$
		
题解 \(by\;zj\varphi\) 对于这个序列,可以近似得把它看成随机的,而对于随机数列,每个数的分布都是均匀的,所以中位数的变化可以看作是常数 那么可以维护一个指向中位数的指针,同时维护有多 ...
 - NOIP模拟22「d·e·f」
		
T1:d 枚举. 现在都不敢随便打枚举了. 实际上我们只关注最后留下的矩阵中最小的长与宽即可. 所以我们将所有矩阵按a的降序排列. 从第\(n-m\)个开始枚举. 因为你最多拿 ...
 - NOIP模拟21+22
		
模拟21确实毒瘤...考场上硬刚T3 2.5h,成功爆零 T1.数论 看这题目就让人不想做,考场上我比较明智的打完暴力就弃掉了,没有打很久的表然后找规律. 正解貌似是乱搞,我们考虑一个比较显然的结论: ...
 - NOIP 模拟 $21\; \rm Park$
		
题解 \(by\;zj\varphi\) 首先,分析一下这个答案:本质上是求在一条路径上,选择了一些点,这些点的贡献是它周围的点权和 - 它上一步的点权 对于一棵树,可以先确定一个根,然后每条路径就可 ...
 - NOIP模拟测试「简单的区间·简单的玄学·简单的填数·简单的序列」
		
简单的区间 $update$ 终于$AC$了 找到$(sum[r]+sum[l](sum表示以中间点为基准的sum)-mx)\%k==0$的点 注意这里$sum$表示是以$mid$为基准点,(即$su ...
 - NOIP模拟13「工业题·卡常题·玄学题」
		
T1:工业题 基本思路 这题有一个重要的小转化: 我们将原来的函数看作一个矩阵,\(f(i,j-1)*a\)相当于从\(j-1\)向右走一步并贡献a,\(f(i-1,j)*b\)相当于从\(i-1 ...
 - NOIP模拟26「神炎皇·降雷皇·幻魔皇」
		
T1:神炎皇 又是数学题,气死,根本不会. 首先考虑式子\(a+b=ab\),我们取\(a\)与\(b\)的\(gcd\):\(d\),那么式子就可以改写成: \[(a'+b')*d=a'b' ...
 - NOIP模拟16:「Star Way To Heaven·God Knows·Loost My Music」
		
T1:Star Way To Heaven 基本思路: 最小生成树. 假如我们将上边界与下边界看作一个点,然后从上边界经过星星向下边界连边,会发现,他会形成一条线将整个矩形分为左右两个部分. ...
 - NOIP模拟14「队长快跑·影魔·抛硬币」
		
T1:队长快跑 基本思路: 离散化·DP·数据结构优化DP 这三个我都没想到....气死. 定义状态数组:\(c[i][j]\)表示在i时最小的a值是j时可以摧毁的最多的水晶数. 那么 ...
 
随机推荐
- .net 知新:【3】.net 5 项目结构说明和发布部署
			
.net 5的项目目录结构和.net framework有些明显的变化,包括显示结构和项目文件,从这两个方面看看有哪些变化. 项目目录结构 就以上篇用的demo项目为例([.net 知新:[2] .N ...
 - 🔥 LeetCode 热题 HOT 100(61-70)
			
207. 课程表 思路:根据题意可知:当课程之间不存在 环状 循环依赖时,便能完成所有课程的学习,反之则不能.因此可以将问题转换成: 判断有向图中是否存在环.使用 拓扑排序法 : 构建 入度表:记录每 ...
 - 华为高斯DB(for MySQL)搭建演示
			
产品架构 云数据库 GaussDB(for MySQL)整体架构自下向上分为三层. 存储层: 基于华为DFV存储,提供分布式.强一致和高性能的存储能力,此层来保障数据的可靠性以及横向扩展能力. 存储抽 ...
 - 组合数取模(lukas)板子
			
求 C(n,m)%mo #include<bits/stdc++.h>#define re register int#define mo 10007#define ll long long ...
 - DNS反向解析,主从服务器,分离解析(内外网)
			
目录 实验一:DNS反向解析 1.安装bind 2.查找配置文件路径 3.配置/etc/named.conf主配置文件 4.修改/etc/named.rfc1912.zones区域配置文件(复制两个) ...
 - Redis-缓存穿透/击穿/雪崩
			
1. 简介 如图所示,一个正常的请求 客户端请求张铁牛的博客. 服务首先会请求redis,查看请求的内容是否存在. redis将请求结果返回给服务,如果返回的结果有数据则执行7:如果没有数据则会继续往 ...
 - 常见的嵌入式linux学习和如何选择ARM芯片问答
			
常见的ARM嵌入式学习问答,设计者和学习者最关心的11个问题: 1. ARM嵌入式是学习硬件好还是学习软件好? 2. 嵌入式软件和硬件,哪一种职位待遇更高?或者说, ...
 - DVWA靶场之XSS(Reflected)通关
			
反射型xss Low: <?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_ ...
 - SwiftUI图片处理(缩放、拼图)
			
采用SwiftUI Core Graphics技术,与C#的GDI+绘图类似,具体概念不多说,毕竟我也是新手,本文主要展示效果图及代码,本文示例代码需要请拉到文末自取. 1.图片缩放 完全填充,变形压 ...
 - STM32—驱动RFID-RC522模块
			
文章目录 一.S50(M1)卡介绍 1.S50(M1)卡基础知识 2.内部信息 3.存取控制 4.数据块的存取控制 5.控制块的存取控 6.工作原理 7.M1与读卡器的通信 二.RC522工程代码详解 ...