首页 > 其他分享 >普及模拟3

普及模拟3

时间:2023-08-22 16:59:37浏览次数:44  
标签:200001 普及 le minn int maxx cnt 模拟

普及模拟3

\(T1\) 最大生成树 \(100pts\)

  • 简化题意:给定一个 \(n(1 \le n \le 1 \times 10^5)\) 个点的完全图,给定各点的点权 \(a_i(1 \le i \le n)\) ,两点间的边权为 \(|a_i-a_j|\) ,求该图的最大生成树。
  • 正解:贪心,考虑到一个点对答案产生的贡献为 \(\max(a_i-\min\limits_{j=1}^{n} a_j,\max\limits_{j=1}^{n} a_j-a_i)\) ,又因为是完全图,易证得连边后一定是符合题意的解。
    ll a[100001];//十年OI一场空,不开long long见祖宗
    int main()
    {
        ll n,i,ans=0;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        for(i=1;i<=n-1;i++)//只需要n-1条边
        {
            ans+=max(a[n]-a[i],a[i]-a[1]);
        }
        cout<<ans<<endl;
        return 0;
    }
    

\(T2\) 红黑树 \(80pts\)

  • 简化题意:给定一棵 \(n(1 \le n \le 1 \times 10^5)\) 个点的有根树, \(1\) 为根节点,初始每个点都是红色,有 \(n\) 次操作,每次操作会把 \(p_i\) 变成黑色,保证操作序列 \(p\) 是一个排列,即每次操作的点都不相同。每次操作完成后,你需要输出有多少个子树是红黑子树,即子树内既包含黑点又包含红点。
  • 部分分:
    • \(20pts\) :对链的情况特判。
    • \(80pts\)(在线做法) :一遍 \(DFS\) 处理出以 \(i(1 \le i \le n)\) 为根的子树大小,每次修改暴力跳父亲直到根节点,卡在了链的测试点上,复杂度为 \(O(n^2)\) ,代码
  • 正解(离线做法):
    • 前置知识:红黑子树的产生与消失都是由改变颜色的这个点造成的。
      • 例如,把节点 \(x\) 变成黑色后,对于所有包含 \(x\) 的子树 \(T\) ,如果 \(x\) 是该子树内第一个变成黑色的点,那么 \(x\) 会让 \(T\) 变成红黑子树;如果 \(x\) 是该子树内最后一个红色的点,那么 \(x\) 会让 \(T\) 变成非红黑子树。
    • 记录下这棵子树中黑点最先出现和最后一个红点变成黑点的时候。
      • 做法一:暴力跳父亲时跳到某个点时,若这个点既不是以这个点的父亲节点为根的子树内最先出现的黑点,也不是最后一个变成黑点的红点时就没有必要跳了,因为不会对答案产生贡献了(这里可能有些绕口,自己可以画图模拟一下)。
        • 复杂度貌似很神奇,官方题解写的是 \(O(n)\) 。
        struct node
        {
        	int nxt,to;
        }e[200001];
        int head[200001],minn[200001],maxx[200001],p[200001],id[200001],fa[200001],cnt=0;//minn表示(····)最早出现,maxx表示最后一个(····)消失
        void add(int u,int v)
        {
        	cnt++;
        	e[cnt].nxt=head[u];
        	e[cnt].to=v;
        	head[u]=cnt;
        }
        void dfs(int x)
        {
        	minn[x]=maxx[x]=id[x];
        	for(int i=head[x];i!=0;i=e[i].nxt)
        	{
        		dfs(e[i].to);
        		minn[x]=min(minn[x],minn[e[i].to]);
        		maxx[x]=max(maxx[x],maxx[e[i].to]);
        	}
        }
        int main()
        {
        	int n,i,j,u,v,ans=0,flag;
        	cin>>n;
        	for(i=1;i<=n-1;i++)
        	{
        		cin>>u;
        		v=i+1;
        		fa[v]=u;
        		add(u,v);
        	}
        	for(i=1;i<=n;i++)
        	{
        		cin>>p[i];
        		id[p[i]]=i;
        	}
        	dfs(1);
        	for(i=1;i<=n;i++)
        	{
        		for(j=p[i];j!=0;j=fa[j])//暴力跳父亲
        		{
        			flag=0;
        			if(minn[j]==id[p[i]])
        			{
        				ans++;
        				flag=1;
        			}
        			if(maxx[j]==id[p[i]])
        			{
        				ans--;
        				flag=1;
        			}
        			if(flag==0)
        			{
        				break;
        			}
        		}
        		cout<<ans<<" ";
        	}
        	return 0;
        }
        
      • 做法二:进行差分维护一下。————隔壁@xrlong的做法
        • 树状数组的区间修改单点查询操作:
        struct node
        {
        	int nxt,to;
        }e[200001];
        int head[200001],minn[200001],maxx[200001],p[200001],id[200001],c[400001],cnt=0;
        int lowbit(int x)
        {
        	return (x&(-x));
        }
        void add(int u,int v)
        {
        	cnt++;
        	e[cnt].nxt=head[u];
        	e[cnt].to=v;
        	head[u]=cnt;
        }
        void dfs(int x)
        {
        	minn[x]=maxx[x]=id[x];
        	for(int i=head[x];i!=0;i=e[i].nxt)
        	{
        		dfs(e[i].to);
        		minn[x]=min(minn[x],minn[e[i].to]);
        		maxx[x]=max(maxx[x],maxx[e[i].to]);
        	}
        }
        void update(int n,int x,int key)
        {
        	for(int i=x;i<=n;i+=lowbit(i))
        	{
        		c[i]+=key;
        	}
        }
        int getsum(int x)
        {
        	int ans=0;
        	for(int i=x;i>0;i-=lowbit(i))
        	{
        		ans+=c[i];
        	}
        	return ans;
        }
        int main()
        {
        	int n,i,j,u,v,ans=0,flag;
        	cin>>n;
        	for(i=1;i<=n-1;i++)
        	{
        		cin>>u;
        		v=i+1;
        		add(u,v);
        	}
        	for(i=1;i<=n;i++)
        	{
        		cin>>p[i];
        		id[p[i]]=i;
        	}
        	dfs(1);
        	for(i=1;i<=n;i++)
        	{
        		update(n,minn[i],1);
        		update(n,maxx[i]-1+1,-1);
        	}
        	for(i=1;i<=n;i++)
        	{
        		cout<<getsum(i)<<" ";
        	}
        	return 0;
        }
        
        • 差分:
        struct node
        {
        	int nxt,to;
        }e[200001];
        int head[200001],minn[200001],maxx[200001],p[200001],id[200001],sum[400001],cnt=0;
        void add(int u,int v)
        {
        	cnt++;
        	e[cnt].nxt=head[u];
        	e[cnt].to=v;
        	head[u]=cnt;
        }
        void dfs(int x)
        {
        	minn[x]=maxx[x]=id[x];
        	for(int i=head[x];i!=0;i=e[i].nxt)
        	{
        		dfs(e[i].to);
        		minn[x]=min(minn[x],minn[e[i].to]);
        		maxx[x]=max(maxx[x],maxx[e[i].to]);
        	}
        }
        int main()
        {
        	int n,i,j,u,v,ans=0;
        	cin>>n;
        	for(i=1;i<=n-1;i++)
        	{
        		cin>>u;
        		v=i+1;
        		add(u,v);
        	}
        	for(i=1;i<=n;i++)
        	{
        		cin>>p[i];
        		id[p[i]]=i;
        	}
        	dfs(1);
        	for(i=1;i<=n;i++)
        	{
        		sum[minn[i]]++;
        		sum[maxx[i]-1+1]--;
        	}
        	for(i=1;i<=n-1;i++)
        	{
        		ans+=sum[i];
        		cout<<ans<<" ";
        	}
        	cout<<"0";
        	return 0;
        }
        

\(T3\) 校门外的树 \(30pts\)

  • 简化题意:给定一个长度为 \(n(1 \le n \le 5 \times 10^5)\) 的序列 \(h\) ,有 \(m(1 \le m \le 5 \times 10^5)\) 次操作,每次操作前对于每一个 \(i(1 \le i \le n)\) 均有 \(h_i\) 增加 \(v_i\),操作如下(对 \(2^{64}\) 取模):
    • 操作一:将 \([l,r]\) 内的 \(v_i(l \le i \le r)\) 增加 \(v\) 。
    • 操作二:求 \(\sum\limits_{i=l}^{r} h_i\) 。
  • 部分分:
    • \(30pts\) :\(n^2\) 暴力枚举。
    • \((30+20=50)pts\) :考虑到没有修改操作,维护一下即可。
  • 正解:建一棵线段树,

\(T4\) 种树 \(0pts\)

  • 简化题意:给定一个长度为 \(n(1 \le n \le 5 \times 10^5)\) 的线段,要求在这个线段上种树,对于每个 \(i(1 \le i \le n)\) 最多只能种一次树,有 \(m\) 组互相独立的计划,内容是第 \(x\) 个位置不能种树,\(|a_i-a_j| \ge k(1 \le i,j \le n,i \ne j)\) ,输出每个计划的方案数对 \(998244353\) 取模的结果。

总结

  • \(T1、T3、T4\)打到 \(8:30\) ,\(9:30\) 打完 \(T2\) 后就去打高斯消元了,导致没有看见 \(T3\) 的对 \(2^{64}\) 取模(打成了 \(2^{60}\) )。
  • \(T3\) 觉得线段树可做,但不想打了。
  • \(T4\) 没有再多想想,没骗到计数类型的 \(DP\) 分。

标签:200001,普及,le,minn,int,maxx,cnt,模拟
From: https://www.cnblogs.com/The-Shadow-Dragon/p/17648463.html

相关文章

  • 「NOIP2008 普及组」ISBN 号码 题解
    前言转自博客,早期黑历史作品。这是本蒟蒻の第一篇题解qwq,发在博客上,还请多多关照.这道题是一道橙题,难度没有太大的问题,对于大犇们来说自然是一遍过的,本蒟就只能调调再交了.题面传送门题目描述每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括99位数字、1......
  • 用友BIP重磅升级,引领企业数智化迈入AI普及应用时代
    8月19日,由用友主办的“2023全球商业创新大会”在上海隆重召开。本次大会以“数据驱动、智能运营”为主题,汇聚众多行业领先企业及各界商业精英,深入探讨解决企业数智化面临的全面数据服务、AI普及应用、升级数智底座、主题化融合应用创新、价值化国产替代及中企出海等诸多课题。会上,......
  • GB28181国标平台测试软件NTV-GBC(包含服务器和模拟客户端)
    GB28181国标平台测试软件NTV-GBC用于对GB28181国标平台进行测试(测试用例需要服务器软件,服务器软件可以是任何标准的国标平台,我们测试使用的是NTV-GBS),软件实现了设备注册、注销、目录查询,消息订阅、INVITE,BYE、KEEPLIVE、OPTION信令。本文档介绍的模拟软件的使用方法。首先下载GBC......
  • 「NOIP2017 普及组」棋盘 题解
    前言一个绿题,风光啊QwQ题面传送门思路怎么走我们定义一个函数dfs(x,y,coin,can,color)x,y表示坐标,coin表示当前的金币数量,color表示当前坐标的颜色,can表示当前是否能施展魔法。再加一个mp数组记录颜色,-1表示无颜色,0表示红色,1表示黄色为什么不直接使用mp[x][y]获取颜......
  • 模拟Linux文件管理员系统-shell实现
    模拟Linux文件管理员系统-shell实现注:此脚本仅供学习使用,具体需要根据实际情况进行测试调整。1系统要求2脚本执行效果2.1管理员登录效果2.2普通用户登录效果2.3密码文件格式用空格隔开,从左往右依次为:用户名密码是否为管理员(1为管理员0为普通用户)是否被锁定(1......
  • CSP模拟27
    A.道路考虑修改后的树任意两点间距离与修改前的关系。例如,\(1\)和\(3\)原本距离为\(2\),现在距离为\(1\);\(3\)和\(4\)原本距离为\(3\),现在距离为\(2\)。我们发现,对于原树中两点间的距离\(\operatorname{dis}\),现在的距离为\(\lfloor\frac{dis+1}{2}\rfloor\)......
  • CSP模拟27
    考的有一点意外,出乎意料。[CF1060E]SergeyandSubway题目链接考场上打假了,乐。设\(dis_{i,j}\)表示\(i\)和\(j\)的树上距离。很容易发现,答案其实就是:\[\sum\lceil\frac{dis_{i,j}}{2}\rceil\]其实就是所有点对的距离,加上距离为奇数的点对的个数,最后除以二就可......
  • 8.21 模拟赛小记
    A.吃饭路上也要锻炼,原P3505[POI2010]TEL-Teleportation咱现在思路通了,代码实现可能得鸽一鸽。两个强强的博客:https://www.cnblogs.com/stoorz/p/12182770.html,https://www.cnblogs.com/reywmp/p/14014611.html。是很难的思维题,涉及乘法原理和图论,用到了分层思想。统计答案时......
  • 【考后总结】8 月 CSP 模拟赛 8
    8.21CSP模拟27晴天-周杰伦故事的小黄花从出生那年就飘着童年的荡秋千随记忆一直晃到现在ReSoSoSiDoSiLaSoLaSiSiSiSiLaSiLaSo吹着前奏望着天空我想起花瓣试着掉落为你翘课的那一天花落的那一天教室的那一间我怎么看不见消失的下雨天我好想......
  • 2023.8.21 模拟赛
    A多次询问\(l,r\),求\(\sum_{x=l}^r\sum_{y=x}^ra_x\otimes\gcd(a_x\sima_y)\),其中$\otimes$是异或。我们先拆解询问,\(Ans=\sum_{x=1}^r\sum_{y=x}^ra_x\otimes\gcd(a_x\sima_y)-\sum_{x=1}^{l-1}\sum_{y=x}^ra_x\otimes\gcd(a_x\sima_y)\)然后离线处理一下......