2024noip模拟赛终结篇
vandan 了,最后一场了!
A 【模板】分治FFT
考虑只有 堆水果的情况,设有 ,则按一定顺序合并的答案是 。可以发现所有情况答案一样。那我们只需要模拟一次合并再乘以方案数即可。
考虑第一次合并, 个数里任选两个,且前后没有顺序,方案数是 。
然后,把合并好的那一堆看成一个,递推上面的过程,发现每一次合并都会使堆总数减一,那么方案数就是 。
点击查看代码
#include<bits/stdc++.h> using namespace std; #define int long long const int N=1e5+5,mod=998244353; int n,a; inline int getc(int n) { return n*(n-1)%mod*499122177%mod; } signed main() { freopen("fft.in","r",stdin); freopen("fft.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>a; int ans=0,sum=a; for(int i=2;i<=n;i++) { cin>>a; ans=(ans+(sum*a)%mod)%mod; sum=(sum+a)%mod; } for(int i=n;i>1;i--) ans=(ans*getc(i))%mod; cout<<ans; }
B 【模板】最近公共祖先
考虑是一棵树时的构造,一定是从下往上选,如果遇到 大于 的情况,就让儿子互相连边,如果剩下一个就传给连向 父亲的边。
这样答案就是 ,构造很成立。
然后如果有非树边,传给父亲等着连。
点击查看代码
#include<bits/stdc++.h> using namespace std; int T; int n,m; const int N=3e5+5; vector<int>e[N]; struct node{ int x,y,z; }; int siz[N],fa[N]; bitset<N>vis;//whether the chain from father to it has been chosen vector<node>ans{}; int lst[N],ins[N]; queue<int>q; void dfs(int u) { vis[u]=ins[u]=1; for(int v:e[u]) { if(!vis[v])dfs(v); } for(int v:e[u]) { if(ins[v]) continue; if(lst[v]) ans.push_back({u,v,lst[v]}),lst[v]=0; else q.push(v); } while(q.size()>=2) { int x=q.front();q.pop(); int y=q.front();q.pop(); ans.push_back({x,u,y}); } if(!q.empty()) { int x=q.front();q.pop(); lst[u]=x; } ins[u]=0; } void Q() { cin>>n>>m; for(int i=1;i<=m;i++) { int u,v;cin>>u>>v; e[u].push_back(v); e[v].push_back(u); } for(int i=1;i<=n;i++)if(!vis[i]) dfs(i); cout<<ans.size()<<"\n"; for(node i:ans) cout<<i.x<<" "<<i.y<<" "<<i.z<<"\n"; } signed main() { freopen("lca.in","r",stdin); freopen("lca.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); T=1; while(T--)Q(); }
C 【模板】普通平衡树
我会。
设 表示当前在 ,上一个数小于(大于) 的最大长度,直接转移即可。
可以发现当 时,最长锯齿子序列长度 满足 的 的个数。可以用线段树对每个子段维护左端和右端情况,和 的个数,然后 pushdown
传下去,查到叶子即可。
点击查看代码
#include<bits/stdc++.h> using namespace std; const int N=3e5+5; int n,q; inline int sgn(int x) { return (x>0)?1:-1; } struct node{ int len,ans,cl,cr,wl,wr; }tr[N<<2]; inline node operator+(node A,node B) { if(!A.len)return B; if(!B.len)return A; if(A.len==1 && B.len==1) { int tmp=sgn(B.wl-A.wl); return (node){2,2,tmp,tmp,A.wl,B.wl}; } if(A.len==1) { int tmp=sgn(B.wl-A.wr); return (node){1+B.len,B.ans+(tmp!=B.cl),tmp,B.cr,A.wl,B.wr}; } if(B.len==1) { int tmp=sgn(B.wl-A.wr); return (node){1+A.len,A.ans+(tmp!=A.cr),A.cl,tmp,A.wl,B.wr}; } int tmp=sgn(B.wl-A.wr); int add=(tmp!=A.cr)+(tmp!=B.cl); return (node){A.len+B.len,A.ans+B.ans-(2-add),A.cl,B.cr,A.wl,B.wr}; } struct SegTree{ #define lid now<<1 #define rid now<<1|1 void pushdown(int now) { tr[lid]=(tr[lid]+tr[now]),tr[rid]=(tr[rid]+tr[now]); tr[now]={0,0,0,0,0,0}; } void modify(int now,int l,int r,int x,int y,node w) { if(x<=l&&r<=y) { tr[now]=(tr[now]+w); return ; }int mid=(l+r)>>1;pushdown(now); if(x<=mid) modify(lid,l,mid,x,y,w); if(y>mid) modify(rid,mid+1,r,x,y,w); } int query(int now,int l,int r,int x) { if(l==r) return tr[now].ans; int mid=(l+r)>>1;pushdown(now); if(x<=mid) return query(lid,l,mid,x); else return query(rid,mid+1,r,x); } }st; signed main() { freopen("odt.in","r",stdin); freopen("odt.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>q; while(q--) { int op; cin>>op; if(op==1) { int l,r,x;cin>>l>>r>>x; st.modify(1,1,n,l,r,{1,1,0,0,x,x}); } else { int x;cin>>x; cout<<st.query(1,1,n,x)<<"\n"; } } }
D 【模板】平面最近点对
上场先开 T4,写了俩小时二分答案写假了。。。
最后还不如人家暴力分高。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析