noip模拟21
开题发现这场考过,定睛一看,发现是省选前最后一场,没改过呀……但是还是讲武德的赛时没提交
A. Median
神奇之处在于 \(1e7\) 个质数居然能线性筛出来~
那么 \(S2\) 可以直接筛出来
接着就是求一个值域 \(2*10^7\) 的数列的固定区间动态中位数
首先各种 \(log\) 算法很好想但是过不了
必须是线性
如果排不了序很难受,可以用桶排来实现
由于数据等同于随机,那么每次暴力移动指针期望复杂度很低,直接暴力扫即可
但是写起来非常难写……
对于 \(k\) 为偶数时考虑维护两个指针,对应两个中位数,并维护出小于等于两个指针的值的个数,如果有一边大于 \(k/2\) 那么移动即可
代码实现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=180000000;
const int MAX=2e7;
const int maxn=1e7+15;
int vis[MAXN+10],pri[maxn],tot,n,k,w,s[maxn],a[maxn],cnt[maxn],cnt1,cnt2,tp1,tp2,sum;
long long ans;
void pre(){
	for(int i=2;i<=MAXN;i++){
		if(!vis[i]){
			vis[i]=i;
			pri[++tot]=i;
		}
		for(int j=1;j<=tot;j++){
			if(1ll*pri[j]*i>MAXN||pri[j]>vis[i])break;
			vis[pri[j]*i]=pri[j];
		}
	}
	return ;
}
int main(){
//	freopen("shuju.in","r",stdin);
//	freopen("my.out","w",stdout);
	pre();
	cin>>n>>k>>w;
	for(int i=1;i<=n;i++){
		a[i]=1ll*pri[i]*i%w;
		s[i]=a[i]+a[i/10+1];
//		cout<<s[i]<<" ";
	}
//	cout<<endl;
	for(int i=1;i<=k;i++){
		cnt[s[i]]++;
	}
	if(k&1){
		for(int i=1;i<=MAX;i++){
			sum+=cnt[i];
			if(sum>=k/2+1){
				if(k&1){
					cnt1=sum-cnt[i];
					cnt2=k-sum;
					tp1=tp2=i;
				}
				break;
			}
			if(cnt[i])tp1=i;
		}
		ans+=tp1+tp2;
		int num=k/2;
		for(int i=1;i<=n-k;i++){
			int last=s[i];
			int now=s[i+k];
			cnt[last]--;
			cnt[now]++;
			cnt1+=-(last<tp1)+(now<tp1);
			cnt2+=-(last>tp1)+(now>tp1);
			while(cnt1>num){
				cnt2+=cnt[tp1];
				tp1--;
				cnt1-=cnt[tp1];
			}
			while(cnt2>num){
				cnt1+=cnt[tp1];
				tp1++;
				cnt2-=cnt[tp1];
			}
			ans+=tp1*2;
//			cout<<tp1<<endl;
		}
	}
	else{
		int num=k/2;
		tp1=tp2=-1;
		for(int i=k;i<=n;i++){
			if(i!=k)cnt[s[i]]++;
			if(s[i]<=tp1)cnt1++;
			if(s[i]<=tp2)cnt2++;
			if(i>k){
				cnt[s[i-k]]--;
				if(s[i-k]<=tp1)cnt1--;
				if(s[i-k]<=tp2)cnt2--;
			}
			while(cnt1<num)cnt1+=cnt[++tp1];
			while(cnt2<num+1)cnt2+=cnt[++tp2];
			while(cnt1>=num+cnt[tp1])cnt1-=cnt[tp1--];
			while(cnt2>=num+1+cnt[tp2])cnt2-=cnt[tp2--];
			ans+=tp1+tp2;
		}
	}
	if(ans&1)printf("%lld.5",ans/2);
	else printf("%lld.0",ans/2);
	return 0;
}
B. Game
首先题意理解清楚了随便打个 \(log\) 算法比较轻松,但是这题还是得 \(O(n)\) 过
相当于维护一个数集,支持加数、取最大值操作,这个还用桶排实现即可
C. Park
神奇的 \(dp\) 题
首先发现作为起点是独特的,贡献为周围点权和,其他地方都需要减去父亲节点的权值
那么需要区分起点和终点,可以设 \(f[u][i]\) 表示以 \(u\) 为根的子树里从某个点为起点到点 \(u\) 的路径撒了 \(i\) 次的最大收获
\(g[u][i]\) 表示从 \(u\) 开始到从 \(u\) 到以 \(u\) 为根子树内一点作为终点的的路径撒了 \(i\) 次的最大收获
那么更新答案为 \(f[u][i]+g[v][m-i]\),考虑更新:
\]
\]
初始化为 \(f[u][i]=sum[u]\),\(g[u][i]=sum[u]-a[father]\)
实现的时候还有一个问题:由于一个是起点另一个是终点,更新答案是根据儿子的顺序来更新的,那么遍历的顺序是有影响的,还需要倒的扫一遍
代码实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e5+5;
const int maxm=2e5+5;
int n,m,hd[maxn],cnt,f[maxn][105],g[maxn][105],ans,x,y,a[maxn],sta[maxn],tp,sum[maxn];
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*f;
}
struct Edge{
	int nxt,to;
}edge[maxm];
void add(int u,int v){
	edge[++cnt].nxt=hd[u];
	edge[cnt].to=v;
	hd[u]=cnt;
	return ;
}
void dfs(int u,int father){
	for(int i=1;i<=m;i++){
		f[u][i]=sum[u];
		g[u][i]=sum[u]-a[father];
	}
	for(int i=hd[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(v==father)continue;
		dfs(v,u);
		for(int j=0;j<=m;j++){
			ans=max(ans,f[u][j]+g[v][m-j]);
		}
		for(int j=1;j<=m;j++){
			f[u][j]=max(f[u][j],max(f[v][j],f[v][j-1]+sum[u]-a[v]));
			g[u][j]=max(g[u][j],max(g[v][j],g[v][j-1]+sum[u]-a[father]));
		}
	}
	for(int i=hd[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(v==father)continue;
		sta[++tp]=v;
	}
	for(int i=1;i<=m;i++){
		f[u][i]=sum[u];
		g[u][i]=sum[u]-a[father];
	}
	while(tp){
		int v=sta[tp--];
		for(int j=0;j<=m;j++){
			ans=max(ans,f[u][j]+g[v][m-j]);
		}
		for(int j=1;j<=m;j++){
			f[u][j]=max(f[u][j],max(f[v][j],f[v][j-1]+sum[u]-a[v]));
			g[u][j]=max(g[u][j],max(g[v][j],g[v][j-1]+sum[u]-a[father]));
		}
	}
	return ;
}
signed main(){
	n=read();
	m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<=n-1;i++){
		x=read();
		y=read();
		add(x,y);
		add(y,x);
		sum[x]+=a[y];
		sum[y]+=a[x];
	}
	dfs(1,0);
	cout<<ans;
	return 0;
}
noip模拟21的更多相关文章
- NOIP模拟21+22
		
模拟21确实毒瘤...考场上硬刚T3 2.5h,成功爆零 T1.数论 看这题目就让人不想做,考场上我比较明智的打完暴力就弃掉了,没有打很久的表然后找规律. 正解貌似是乱搞,我们考虑一个比较显然的结论: ...
 - NOIP 模拟 $21\; \rm Median$
		
题解 \(by\;zj\varphi\) 对于这个序列,可以近似得把它看成随机的,而对于随机数列,每个数的分布都是均匀的,所以中位数的变化可以看作是常数 那么可以维护一个指向中位数的指针,同时维护有多 ...
 - NOIP 模拟 $21\; \rm Park$
		
题解 \(by\;zj\varphi\) 首先,分析一下这个答案:本质上是求在一条路径上,选择了一些点,这些点的贡献是它周围的点权和 - 它上一步的点权 对于一棵树,可以先确定一个根,然后每条路径就可 ...
 - NOIP 模拟 $21\; \rm Game$
		
题解 考试的时候遇到了这个题,没多想,直接打了优先队列,但没想到分差竟然不是绝对值,自闭了. 正解: 值域很小,所以我们开个桶,维护当前最大值. 如果新加入的值大于最大值,那么它肯定直接被下一个人选走 ...
 - Noip模拟21(持续翻车)2021.7.20
		
读题总是读错是不是没救了... T1 Median 中位数:按顺序排列的一组数据中居于中间位置的数. 能用上的高亮符号都用上了... 当时忘了就离谱.... 理解什么是中位数(真是个憨憨)后就可以开始 ...
 - NOIP模拟 21
		
可爱的Dybala走了..(当然只是暂时) 又考了大众分.从rank5到rank17一个分. T1 折纸 秒切,爽啊 天皇偷看我代码,结束看见我A了还很惊讶,说我代码有锅 好沙雕哦 就跟个2b似的. ...
 - [考试总结]noip模拟21
		
中位数要排序!!!!!! 中位数要排序!!!!!! 中位数要排序!!!!!! 中位数要排序!!!!!! 中位数要排序!!!!!! 分差不加绝对值!!!! 分差不加绝对值!!!! 分差不加绝对值!!!! ...
 - NOIP模拟21:「Median·Game·Park」
		
T1:Median 线性筛+桶+随机化(??什么鬼?). 首先,题解一句话秀到了我: 考虑输入如此诡异,其实可以看作随机数据 随机数据?? 这就意味着分布均匀.. 又考虑到w< ...
 - NOIP模拟17.9.21
		
NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...
 
随机推荐
- Thinkphp 分页应用
			
$Table = M('Table'); $count = $Table ->where()->count(); $Page = new \Think\Page($count ...
 - P2470 压缩 TJ
			
前言 洛谷题解 题目传送门 正解:区间/线性 dp(本篇题解介绍线性做法) 人生第一道紫题! 也是今天考试看自闭了就没做的 T4,结果没想到是紫,虽然是一道水紫呢-- 考试的 T5 是跳房子,蓝题 q ...
 - 解决:无法从 Windows 应用商店下载。请检查网络连接
			
今天在安装wsl的时候,装了几次一直中断,一直提示正在从Windows 应用商店下载,网络无法连接... 每次都是加载到2%就断了.网上搜了一圈,找到以下2种解决办法: 修改DNS把DNS修改为微软的 ...
 - squid异常停止的排查步骤
			
今天重启squid的时候发现,squid启动后,status 一会就stop了 whoami@blackman:~/script/AutoProxy-master/main/server$ sudo ...
 - python grequest模块使用备忘录
			
手里上有一批链接,需要检查他们是否已经被删除.本来是想用多线程的,但是考虑了下一个是实现起来稍繁琐.而且性能不理想,单机基本超过10线程基本上就没有太多增益了. 所以考虑了下,还是决定用异步IO. 在 ...
 - Java基础——自增自减及初识Math类
			
自增自减及初识Math类 public class Demon05 { public static void main(String[] args) { // ++ -- 自 ...
 - HTTP头参数详解及其中的危险
			
一.重要的头参数 user_agent 发出请求的用户信息 X-Forwarded-For 表示 HTTP 请求端真实 IP(格式:X-Forwarded-For: client, proxy1, p ...
 - Pikachu-暴力破解模块
			
一.概述 "暴力破解"是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取. 其过程就是使用大量的认证信息在认证接口进行尝试登录,直到得到正确的结果. 为 ...
 - Mybatis-Plus入门学习笔记(一)
			
本文内容 了解Mybatis-Plus 整合Mybatis-Plus 1.了解Mybatis-plus 1.1.Mybatis-Plus介绍 MyBatis-Plus(简称 MP)是一个 MyBati ...
 - linux 的删除
			
1,删除 命令行 rm -rf 文件夹名称 2,下载 wget 网址 -------------------- 查找ES进程号 ps -ef | grep elastic kill -9 3250 3 ...