10.4 - 11.4 改题纪要

10.4 - 11.4 改题纪要

还是决定写一起。

等写完了就会把问号改了

冲刺CSP联训模拟2

以后见了计数先想容斥!!!

  1. T1 挤压

    按位拆开,每两位一块考虑,枚举每个数是否选,\(O(nlog^2n)\) 的。

  2. T2 工地难题

    考虑恰好比较难做,先前缀和变成至少。

    发现 \(0\) 个数一定,其将序列分成若干小段,每段有若干 \(1\)

    相当于是 \(\sum x_i = k(x_i<k)\) 的形式,直接容斥即可。

  3. 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\)

  4. T4 纽带

    析合树上 \(dp\),这是我现在能改的???

多校A层冲刺NOIP2024模拟赛03

两签一原(虽然原不是都做过,但是也是签)。

  1. 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 是吧。

  1. T1 邻面合并

    发现 \(m\) 很小,直接用 vector 状压即可。

    也可以压二进制,发现对于每一层那些地方会有矩形是固定的,状态只是分割点,可以 \(2^8\) 压起来。

  2. T2 光线追踪

    考虑横线和竖线互不影响,分开考虑。

    每条线对应一个斜率范围,离散化后就是区间推 \(\min\),单点查。

    注意边界。

  3. T3 百鸽笼

    好题,单开了一篇 this

  4. 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

  1. T4 表达式:

    首先观察性质,发现除了暴力以外所有模数都可以分解成较小的互质数相乘。

    直接线段树维护值域套 CRT 合并即可。

多校A层冲刺NOIP2024模拟赛06

  1. T3 一个真实的故事:

    首先发现值域很小,考虑直接用线段树维护,合并的时候暴力将左边最靠右和右边最靠左的不同 \(k\) 个归并扫描线即可。

    有和值域无关的做法,可以看 this马上就写写了)

  2. T4 异或区间(xor):

    经典结论:对于每个值所管辖的 \(max\) 区间中左边和右边较小的一边的和是 \(n\log n\) 级的。

    证明可以考虑笛卡尔树。

    于是有两种做法,一是用可持久化 trie 每次遍历较小区间,一是建笛卡尔树跑启发式。

csp-s模拟11

不是非多校的题这么难。(断句:不是、非多校的题这么难?)

  1. T3 暴雨:

    考虑对于两边都漏的显然是不好整,考虑枚举前 \(k\) 大来作为最大的分割左右(比它大的直接铲掉)。

    考虑只有一边要枚举,设 \(dp_{i,j,k}\) 表示当前在 \(i\),挖了 \(k\) 下,前面最高的是 \(k\),暴力转移是 \(O(n^2k)\) 的,但是发现最高的只有可能是前 \(k\) 大,于是可以做到 \(O(nk^2)\),总复杂度 \(O(nk^3)\)

    有个简单的实现是将第三维保留 \(n\) 的大小,将第一维滚掉优化空间,这样不用下标的重编号。

    当我们写出 \(dp\) 后,我们发现枚举前 \(k\) 大纯唐,可以直接将前缀后缀用一个拼起来转移,不用每次重做一遍,复杂度变为 \(nk^2\)

  2. T2 AVL 树:

    根据前序遍历或中序遍历贪心即可,因为树高是 \(\log\) 的每次暴力跳爹来更新右子树最少选的个数,细节不少。

  3. T4 置换:

    首先是置换环经典结论,其次数等于 \(\operatorname{lcm\{环长\}}\)

    考虑 \(dp\),设 \(dp_{i,j}\) 表示以 \(i\) 为环长,\(j\)\(\operatorname{lcm}\) 的概率,枚举长度和个数转移即可,用方案数的乘上 \(\operatorname{lcm}^2\),注意在最后除掉 \(n!\)

    \(map\) 轻松 60pts,考虑优化。

    发现对于一个 \(\ge \sqrt n\) 的因子,其最大次数是一,先提出来,\(dp\) 完放回即可。

  4. T5 传统题:

    是个好题,先放这提醒我改。

多校A层冲刺NOIP2024模拟赛07

  1. 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 统计左区间对右区间的贡献,线段树合并即可。

  2. 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

  1. T3 战场模拟器 (simulator) :

    考虑每个人只会死一次,盾也只有一次贡献,用线段树维护区间 \(min\) 暴力改即可(也可以用分块微调快长)。

  2. 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

  1. T3 小 y 的数论

    先考虑全局,这个是简单的,显然取长剖后的前 \(k\) 长链即可。

    考虑区间,显然可以直接推到虚树上,考虑合并,对于 \(k=2\) 时其有优秀性质:直径可以合并,类似的,我们猜测 \(k>2\) 时也有可以合并的性质,其实确实有,证明也比较显然,考虑每次必然取的时长链端点,而端点又一定是之前的端点。

    于是有了好做法,ST 表维护,合并时对于左右各 \(k\) 个点建虚树,长剖求答案,查询时依然这样合并。

    稍微分析一下复杂度就知道,根本过不去!

    考虑分块来平衡复杂度,每 \(K\) 个分一块,块间维护 ST 表,最后将散块暴力合并即可。

  2. T4 小j 的组合

    是签,想不到吧。

    考虑复制一个点等价于让一个点的经过次数 \(+1\),考虑树上的哈密顿路就是 \(dfs\) 一遍,发现只有一条链可以只经过一遍,于是就是找直径板子。

多校A层冲刺NOIP2024模拟赛09

  1. 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\) 对,最后桶排跑最小生成树即可。

  2. T4 区间 (interval)

    首先离线,将询问离线到右端点,扫描线。

    考虑如何维护第一个限制,用单调栈即可。

    考虑第二个限制,直接上线段树,于是变成了区间历史和板子。

多校A层冲刺NOIP2024模拟赛10

  1. T3 TG393. 列表

    this(罕见的提前写好了)

后面的基本都是逆天区分度,不写了。

也许会把几个不太逆天的单改一下。

好像还有一道『T5 传统题』没改,别急,一定会改的。

完结撒花!!正好一个月

P


posted @ 2024-11-04 19:51  xrlong  阅读(77)  评论(1编辑  收藏  举报