10.4 - 11.4 改题纪要
10.4 - 11.4 改题纪要
还是决定写一起。
等写完了就会把问号改了
冲刺CSP联训模拟2
以后见了计数先想容斥!!!
-
T1 挤压
按位拆开,每两位一块考虑,枚举每个数是否选,\(O(nlog^2n)\) 的。
-
T2 工地难题
考虑恰好比较难做,先前缀和变成至少。
发现 \(0\) 个数一定,其将序列分成若干小段,每段有若干 \(1\)。
相当于是 \(\sum x_i = k(x_i<k)\) 的形式,直接容斥即可。
-
T3 星空遗迹
首先发现点显然的性质。
- 连续一段的长度无意义。
- 如果一段中两端(如果只有一端就是一端)都是能赢他的,就可以删掉这一段。
- 依次删掉后一定只剩下一段相同的。
由此可以有单调栈写法,保证任意一个非栈顶元素一定会输给其下一个(也可写逆天并查集,但好像不太好扩展到正解)。
考虑修改。
对于每个元素,维护栈在加入它后的大小,设其为 \(f_i\):
\[f_i=\begin{cases} f_i+1 & s_i<s_{i-1}\vee i=1\\f_i & s_i=s_{i-1}\\\max(f_i-1,1) & s_i>s_{i-1}\end{cases} \]最后的答案就是最后一个为 \(1\) 的位置
发现这个 \(max\) 很难整,考虑直接去掉,发现其相当于是连续下降,容易证明有一个好的性质:只有最小值和最后一个 \(1\) 一一对应。
但其实也不用特意找最后一个,考虑升降是对称的,所以栈大小相同的元素一定是一样的。
维护单点改,前缀和的区间 \(min\),可以直接上线段树上二分,也可以前缀和变成区间加,区间 \(min\)。
-
T4 纽带
析合树上 \(dp\),这是我现在能改的???
多校A层冲刺NOIP2024模拟赛03
两签一原(虽然原不是都做过,但是也是签)。
-
T4 量子隧穿问题(experiment):
挺好的题,@wang54321 不要因为你实现屎就说题屎。
发现记录有没有猫的方案数比较麻烦,这里我们记录概率。
显然基环树,先考虑只是一棵树怎么做,考虑设 \(dp_{i,j}\) 表示第 \(i\) 时刻 \(j\) 的概率,依次枚举边转移即可,转移就是考虑猫是否转移。
发现有环就挂了,因为考虑若 \(p(p<1)\) 的概率有猫,\(1-p\) 的概率没猫,在环上转移一圈时每一个都对 \(p\) 有依赖,在最后转移到起点时就会将依赖有猫和依赖没猫的结合,导致错误。
可能可以通过逆天小技巧进行最后一步转移,但这里介绍比较简单的钦定。
考虑题解做法,钦定第一条边的左右端点来断边,钦定其在跳环前是 \(1,1\)、\(0,1\)、\(1,0\)、\(0,0\) 分讨,最后乘上其概率即可。
发现 \(0,1\) 和 \(1,0\) 在跳第一次之后一模一样,可以只分讨三种。
考虑有冲突的关键是依赖有猫和依赖没猫的概率的冲突,只钦定环上第一次跳的点即可,只用分讨两种。
csp-s模拟9
accoders 的模拟赛出过了,于是有了这个代替,不是我们 csp/noip 模拟赛出两道 UNR 是吧。
-
T1 邻面合并
发现 \(m\) 很小,直接用
vector
状压即可。也可以压二进制,发现对于每一层那些地方会有矩形是固定的,状态只是分割点,可以 \(2^8\) 压起来。
-
T2 光线追踪
考虑横线和竖线互不影响,分开考虑。
每条线对应一个斜率范围,离散化后就是区间推 \(\min\),单点查。
注意边界。
-
T3 百鸽笼
好题,单开了一篇 this
-
T4 滑稽树下你和我
计算几何,没准会改。真的改了。
首先需要知道怎么求点到线段距离,考虑先点积判断是否垂足在线段上,用叉积的模除以底来求垂线长。
可以看 this
二分答案。
首先有结论,如果在两个点在两条线段一端时满足,在另一端时也满足,则一定有满足要求的一种移动。
证明就是发现将一条线段放平,另一条一定时单调的。
于是在特殊性质时可以直接枚举两个点来转移。
考虑在非特殊性质时,会有一个点在一条边上等另一个,考虑将边变成点,由于有结论,在最优时一定是等的点在离另一个点最近的点上,直到另一个点到达是其依然在最近的点上。
形如:
形如(图不咋地,凑合吧)
考虑将边变成点,其和其他点的距离就是点到直线距离,可以直接转移,但有小常数的做法,设 \(dp_{i,j}\) 表示一个点在 \(i\) 边上,另一个在 \(j\) 点上是否可行,发现其也可以表示所有情况。
放个代码吧
#include<bits/stdc++.h> using namespace std; using llt=long long; using llf=long double; using ull=unsigned long long; #define endl '\n' #ifdef LOCAL FILE *InFile=freopen("in_out/in.in","r",stdin),*OutFile=freopen("in_out/out.out","w",stdout); #else FILE *InFile=stdin,*OutFile=stdout; #endif const double Eps=1e-8; int Cmp(double a,double b){return fabs(a-b)<Eps?0:(a<b?-1:1);} struct Pnt{double x,y; Pnt(){} Pnt(double a,double b):x(a),y(b){}}; double Dis(const Pnt &a,const Pnt &b){return sqrtl((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} struct Vec{ double x,y; Vec(){} Vec(double a,double b):x(a),y(b){} Vec(const Pnt &a,const Pnt &b):x(b.x-a.x),y(b.y-a.y){} Vec &operator+=(const Vec &b){x+=b.x,y+=b.y; return *this;} Vec operator-()const{return Vec(-x,-y);} Vec &operator-=(const Vec &b){*this+=-b; return *this;} Vec operator+(const Vec &b)const{Vec ans=*this; return ans+=b;} Vec operator-(const Vec &b)const{Vec ans=*this; return ans-=b;} Vec &operator*=(double k){x*=k,y*=k; return *this;} friend Vec operator*(double k,Vec a){a*=k; return a;} Vec operator*(double k)const{return k*(*this);} double operator*(const Vec &b)const{return x*b.x+y*b.y;} double operator^(const Vec &b)const{return x*b.y-y*b.x;} }; struct Lin{ Pnt a,b; Lin(){} Lin(const Pnt &a1,const Pnt &a2):a(a1),b(a2){} Lin(double a1,double a2,double a3,double a4):a(a1,a2),b(a3,a4){} operator Vec()const{return Vec(a,b);} operator double()const{return Dis(a,b);} }; double Dis(const Pnt &p,const Lin &l){ if(Vec(l.a,p)*Vec(l.a,l.b)<0) return Dis(p,l.a); if(Vec(l.b,p)*Vec(l.b,l.a)<0) return Dis(p,l.b); return abs(Vec(l.a,l.b)^Vec(l.a,p))/double(l); } const int N=1003; struct Gph{ int hd[N],to[N<<1],nt[N<<1],wt[N<<1],tot=1; void Add(int u,int v,int w){wt[++tot]=w,to[tot]=v,nt[tot]=hd[u],hd[u]=tot;} void ADD(int u,int v,int w){Add(u,v,w),Add(v,u,w);} #define For_to(i,u,v,g) for(int i=g.hd[u],v=g.to[i];i;i=g.nt[i],v=g.to[i]) }g; int n,sa,sb,cd[N]; Pnt cp[N]; Lin cl[N]; bool dp[N][N]; bool Chk(double lim){ memset(dp,0,sizeof(dp)); queue<pair<int,int>> que; auto Lim=[&lim](double a){return Cmp(a,lim)<=0;}; For_to(i,sa,v,g) if(Lim(Dis(cp[sb],cl[g.wt[i]]))) dp[sb][g.wt[i]]=1,que.emplace(sb,i); For_to(i,sb,v,g) if(Lim(Dis(cp[sa],cl[g.wt[i]]))) dp[sa][g.wt[i]]=1,que.emplace(sa,i); while(!que.empty()){ auto tmp=que.front(); que.pop(); int p=tmp.first,l=tmp.second; if(cd[p]==1&&((cd[g.to[l]]==1&&Lim(Dis(cp[p],cp[g.to[l]])))||(cd[g.to[l^1]]==1&&Lim(Dis(cp[p],cp[g.to[l^1]]))))) return 1; For_to(i,p,v,g){ if(!dp[v][g.wt[l]]&&Lim(Dis(cp[v],cl[g.wt[l]]))) dp[v][g.wt[l]]=1,que.emplace(v,l); int np=g.to[l],nl=g.wt[i]; if(!dp[np][nl]&&Lim(Dis(cp[np],cl[nl]))) dp[np][nl]=1,que.emplace(np,i); np=g.to[l^1]; if(!dp[np][nl]&&Lim(Dis(cp[np],cl[nl]))) dp[np][nl]=1,que.emplace(np,i); } } return 0; } int main(){ ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin>>n>>sa>>sb; cout<<fixed<<setprecision(10); for(int i=1;i<=n;++i) cin>>cp[i].x>>cp[i].y; for(int i=1;i<n;++i){int a,b; cin>>a>>b; cl[i]=Lin(cp[a],cp[b]),g.ADD(a,b,i),++cd[a],++cd[b];} double l=Dis(cp[sa],cp[sb]),r=2e6; for(int i=1;i<=40;++i){ double mid=(l+r)/2; if(Chk(mid)) r=mid; else l=mid; } cout<<l; }
多校A层冲刺NOIP2024模拟赛04
-
T4 表达式:
首先观察性质,发现除了暴力以外所有模数都可以分解成较小的互质数相乘。
直接线段树维护值域套 CRT 合并即可。
多校A层冲刺NOIP2024模拟赛06
-
T3 一个真实的故事:
首先发现值域很小,考虑直接用线段树维护,合并的时候暴力将左边最靠右和右边最靠左的不同 \(k\) 个归并扫描线即可。
有和值域无关的做法,可以看 this(
马上就写写了) -
T4 异或区间(xor):
经典结论:对于每个值所管辖的 \(max\) 区间中左边和右边较小的一边的和是 \(n\log n\) 级的。
证明可以考虑笛卡尔树。
于是有两种做法,一是用可持久化 trie 每次遍历较小区间,一是建笛卡尔树跑启发式。
csp-s模拟11
不是非多校的题这么难。(断句:不是、非多校的题这么难?)
-
T3 暴雨:
考虑对于两边都漏的显然是不好整,考虑枚举前 \(k\) 大来作为最大的分割左右(比它大的直接铲掉)。
考虑只有一边要枚举,设 \(dp_{i,j,k}\) 表示当前在 \(i\),挖了 \(k\) 下,前面最高的是 \(k\),暴力转移是 \(O(n^2k)\) 的,但是发现最高的只有可能是前 \(k\) 大,于是可以做到 \(O(nk^2)\),总复杂度 \(O(nk^3)\)。
有个简单的实现是将第三维保留 \(n\) 的大小,将第一维滚掉优化空间,这样不用下标的重编号。
当我们写出 \(dp\) 后,我们发现枚举前 \(k\) 大纯唐,可以直接将前缀后缀用一个拼起来转移,不用每次重做一遍,复杂度变为 \(nk^2\)。
-
T2 AVL 树:
根据前序遍历或中序遍历贪心即可,因为树高是 \(\log\) 的每次暴力跳爹来更新右子树最少选的个数,细节不少。
-
T4 置换:
首先是置换环经典结论,其次数等于 \(\operatorname{lcm\{环长\}}\)。
考虑 \(dp\),设 \(dp_{i,j}\) 表示以 \(i\) 为环长,\(j\) 为 \(\operatorname{lcm}\) 的概率,枚举长度和个数转移即可,用方案数的乘上 \(\operatorname{lcm}^2\),注意在最后除掉 \(n!\)
用 \(map\) 轻松 60pts,考虑优化。
发现对于一个 \(\ge \sqrt n\) 的因子,其最大次数是一,先提出来,\(dp\) 完放回即可。
-
T5 传统题:
是个好题,先放这提醒我改。
多校A层冲刺NOIP2024模拟赛07
-
T3 距离(distance):
首先用树形 \(dp\) 经典结论,每次合并子树用 \(sz_u\times sz_v\)(这里 \(sz_u\) 是已经合并的子树大小)总复杂度 \(n^2\),证明考虑每个点对只会在 \(lca\) 处有 \(1\) 的贡献。
但正解和这个没关系。
考虑 \(\min\max\) 容斥,将 \(\max{|x_a-x_b|,|y_a-y_b|}\) 也就是切比雪夫距离转曼哈顿距离,问题就变成了求解四个不相关的绝对值。
暴力可以树状数组套 dsu on tree,用巴雷特约减可以卡过 accoder,过不了学校 oj。
可以直接用值域线段数,类似 cdq 统计左区间对右区间的贡献,线段树合并即可。
-
T4 团队选拔(selection):
考虑一个 \(n^3\) 做法:设 \(dp_{i,j}\) 表示前缀是 \(i\),\(\gcd\) 是 \(j\) 的方案数,最后枚举一遍 \(a_i\) 和 \(\gcd\) 转移即可。
发现显然结论,每个数为起点的所有区间的 \(\gcd\) 的种类数是 \(\log\) 级别的,\(n\) 个数就是 \(n\log n\) 级别的。
于是我们用栈处理出每个数前后缀区间的 \(\gcd\) 种类所对应的左右端点区间,具体的就是每次加入时将当前栈遍历一遍,和这个数取 \(\gcd\) 后合并相同区间,显然任意时刻栈的大小是 \(\log\) 级的。
然后枚举每个 \(\gcd\),总共有用的转移点一共就 \(n\log n\) 个,对于没有转移点的直接区间推平,用线段树维护,答案是区间加,差分即可。
多校A层冲刺NOIP2024模拟赛08
-
T3 战场模拟器 (simulator) :
考虑每个人只会死一次,盾也只有一次贡献,用线段树维护区间 \(min\) 暴力改即可(也可以用分块微调快长)。
-
T4 点亮 (light) :
首先经过转换题意,发现其每个联通块都是一个重边加上一些边组成的树,联通块个数就是重边个数。
容斥,设 \(g(x)\) 表示钦定(至少) \(x\) 条重边的方案数。
不太显然的是:
\[g(x)=\frac{n!}{2^x(n-2i)!}\prod_{j=1}^x \frac{1}{\binom{n}{2}-\binom{n-2j}{2}} \]解释就是在 \(\prod\) 后面的部分是钦定选的边求概率,考虑从大到小按边权加边,将 \(j\) 理解为从 \(x\) 到 \(1\) 可能好理解一点,\(\prod\) 前面的部分是在选这 \(x\) 条边(式子约了一个 \(i!\))。
csp-s模拟12
-
T3 小 y 的数论
先考虑全局,这个是简单的,显然取长剖后的前 \(k\) 长链即可。
考虑区间,显然可以直接推到虚树上,考虑合并,对于 \(k=2\) 时其有优秀性质:直径可以合并,类似的,我们猜测 \(k>2\) 时也有可以合并的性质,其实确实有,证明也比较显然,考虑每次必然取的时长链端点,而端点又一定是之前的端点。
于是有了好做法,ST 表维护,合并时对于左右各 \(k\) 个点建虚树,长剖求答案,查询时依然这样合并。
稍微分析一下复杂度就知道,根本过不去!
考虑分块来平衡复杂度,每 \(K\) 个分一块,块间维护 ST 表,最后将散块暴力合并即可。
-
T4 小j 的组合
是签,想不到吧。
考虑复制一个点等价于让一个点的经过次数 \(+1\),考虑树上的哈密顿路就是 \(dfs\) 一遍,发现只有一条链可以只经过一遍,于是就是找直径板子。
多校A层冲刺NOIP2024模拟赛09
-
T1 排列最小生成树
不是,\(n\sqrt n\log n\) 过不去 \(5\times 10^4\) 啊啊啊!
首先发现边权 \(> n\) 的点对一定不会选,因为显然从 \(1\) 连到 \(n\) 连一条链就没有边权 \(>n\)。
发现两个点能连当且仅当 \(|i-j|<=\sqrt n\) 或 \(|p_i-p_j|<=\sqrt n\),其一共只有 \(n\sqrt n\) 对,最后桶排跑最小生成树即可。
-
T4 区间 (interval)
首先离线,将询问离线到右端点,扫描线。
考虑如何维护第一个限制,用单调栈即可。
考虑第二个限制,直接上线段树,于是变成了区间历史和板子。
多校A层冲刺NOIP2024模拟赛10
-
T3 TG393. 列表
后面的基本都是逆天区分度,不写了。
也许会把几个不太逆天的单改一下。
好像还有一道『T5 传统题』没改,别急,一定会改的。
完结撒花!!正好一个月
P
本文来自博客园,作者:xrlong,转载请注明原文链接:https://www.cnblogs.com/xrlong/p/18447058
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。