[考试记录] 2024.11.22 noip模拟赛19
T1 镜的绮想 (mirror)
考虑维护中点 坐标数量,,不过不用除。枚举所有相同 坐标点对即可。
#include<bits/stdc++.h> using namespace std; constexpr int N = 5e3 + 5, MX = 2e6 + 5; int a[N<<1], pos[N<<1], cnt, ans, val[MX<<1]; struct node{ int x, y; }tn[N], fn[N]; vector<int> tvec[N<<1], fvec[N<<1]; int main(){ freopen("mirror.in", "r", stdin); freopen("mirror.out", "w", stdout); ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n, m; cin>>n>>m; for(int i=1; i<=n; ++i) cin>>tn[i].x>>tn[i].y, a[++cnt] = tn[i].x; for(int i=1; i<=m; ++i) cin>>fn[i].x>>fn[i].y, a[++cnt] = fn[i].x; sort(a+1, a+1+cnt); cnt = unique(a+1, a+1+cnt) - a - 1; for(int i=1; i<=n; ++i) tvec[lower_bound(a+1, a+1+cnt, tn[i].x)-a].emplace_back(tn[i].y); for(int i=1; i<=m; ++i) fvec[lower_bound(a+1, a+1+cnt, fn[i].x)-a].emplace_back(fn[i].y); for(int i=1; i<=cnt; ++i) if(!tvec[i].empty() && !fvec[i].empty()) for(int tv : tvec[i]) for(int fv : fvec[i]) ++val[tv + fv + MX], ans = max(ans, val[tv + fv + MX]); return cout<<ans, 0; }
T2 万物有灵 (animism)
不知道最大独立集是什么,然后就跳了,我有可能真的错过了 100pts
规律是简单的,我们称深度为 的树为基础树。那么最大独立集即为从树的最底层开始,取一层跳过一层以此类推。考虑利用一下周期性,当 为偶数的时候计算出基础树的奇数层的节点总数,和偶数层的节点总数,然后计算一下整棵树包含多少颗基础树。令 表示基础树的叶子数量,那么基础树的数量即为 ,等比数列求和即可。不过考虑到没有逆元的情况,可以使用矩阵乘法或者递归求解。对于 为奇数的情况,直接将 即可转化。
#include<bits/stdc++.h> using namespace std; #define int long long #define it __int128 constexpr int N = 5e5 + 5; int n, k, M, a[N<<1], b[N<<1]; inline int qpow(int a, int k){ int res = 1; while(k){ if(k & 1) res = (it)res * a % M; a = (it)a * a % M; k >>= 1; } return res; } inline int add(initializer_list<int> Add){ int res = 0; for(int v : Add) res = res + v >= M ? res + v - M : res + v; return res; } inline int mul(initializer_list<int> Mul){ int res = 1; for(int v : Mul) res = (it)res * v % M; return res; } inline void eg(int a, int b, int &x, int &y){ if(!b) return x = 1, y = 0, void(); eg(b, a%b, y, x); y -= a / b * x; } inline int inv(int k){ int x = 0, y = 0; eg(k, M, x, y); x = ((x % M) + M) % M; if(x < 0) printf("fvv\n"), exit(0); return x; } signed main(){ freopen("animism.in", "r", stdin); freopen("animism.out", "w", stdout); cin>>n>>k>>M; for(int i=1; i<=k; ++i) cin>>a[i]; for(int i=k+1; i<=k<<1; ++i) a[i] = a[i-k]; if(k & 1) k *= 2; b[1] = a[1]; int sum1 = a[1], sum2 = 0; for(int i=2; i<=k; ++i){ b[i] = mul({b[i-1], a[i]}); if(i & 1) sum1 = add({sum1, b[i]}); else sum2 = add({sum2, b[i]}); } if(!((n % k) & 1)){ int res = 1, lst = qpow(b[k], n/k); int sum = mul({lst-1, inv(b[k]-1)}); res = add({res, mul({sum, sum2})}); for(int i=2; i<=n%k; i+=2) res = add({res, mul({b[i], lst})}); cout<<abs(res); exit(0); } else { int res = 0, lst = qpow(b[k], n/k); int sum = mul({lst-1, inv(b[k]-1)}); res = add({res, mul({sum, sum1})}); for(int i=1; i<=n%k; i+=2) res = add({res, mul({b[i], lst})}); cout<<abs(res); exit(0); } }
T3 白石溪 (creek)
考场上苦思冥想如何优化 45pts dp 没想到是个贪心……
没太明白,颓过去的……
#include<bits/stdc++.h> using namespace std; constexpr int B = 1 << 15; char buf[B], *p1 = buf, *p2 = buf; #define gt() (p1==p2 && (p2=(p1=buf)+fread(buf, 1, B, stdin), p1==p2) ? EOF : *p1++) template <typename T> inline void rd(T &x){ x = 0; int f = 0; char ch = gt(); for(; !isdigit(ch); ch = gt()) f ^= ch == '-'; for(; isdigit(ch); ch = gt()) x = (x<<1) + (x<<3) + (ch^48); x = f ? -x : x; } template <typename T, typename ...TT> inline void rd(T &x, TT &...y){ rd(x), rd(y...); } #define int long long int p[1000005]; signed main(){ freopen("creek.in", "r", stdin); freopen("creek.out", "w", stdout); int n, c, d; rd(n, c, d); int ans = 0, res = 0; for(int i=1, a, b; i<=n; ++i){ rd(a, b); ans += a; p[i] = a - b - (i-1) * c - (n-i) * d; } sort(p+1, p+1+n); res = ans; for(int i=1; i<=n; ++i) ans -= p[i], res = max(res, ans - (c+d)*i*(i-1)/2); return printf("%lld", res), 0; }
T4 上山岗 (uphill)
首先考虑构造出匹配数最多的方案,采用 田忌赛马 策略,先将能力值排序,从小到大枚举每一个登山队员找到最靠右的合法匹配位置,这样构造下来字典序是较小的,并且匹配数是最多的。
然后考虑在保证匹配数最多的情况下移动。贪心地,按能力值从大到小枚举队员。如果该队员当前有匹配的位置,那么找到最左端的未匹配的位置来置换,这样的位置是确定下来的;如果没有匹配的位置,那就随便找到一个最靠左没有被确定的位置,如果这个位置被其他人匹配过了,那就强制把那个人拆下来,把现在这个人换上去。因为比他小的人都有匹配,那这个人一定也有匹配。由于从大到小确定位置构造,这样的字典序一定最大。
具体维护方式可以使用两颗线段树,一棵维护没有被匹配的位置的最小值,一棵维护没有被确定的位置的最小值。支持单点修改,查最靠左、右最小值,线段树上二分即可。复杂度 。
#include<bits/stdc++.h> using namespace std; constexpr int N = 5e5 + 5, Inf = 1e9; int n, a[N], b[N], mch[N], ans[N]; struct ST{ #define ls (id << 1) #define rs (id << 1 | 1) #define pushup(id) t[id].mn = min(t[ls].mn, t[rs].mn) struct node{ int l, r, mn; }t[N<<2]; inline void build(int id, int l, int r){ t[id] = node{l, r, 0}; if(l == r) return t[id].mn = a[l], void(); int mid = (l + r) >> 1; build(ls, l, mid), build(rs, mid+1, r); pushup(id); } inline void modify(int id, int pos, int val){ if(pos <= 0 || pos > n) return; if(t[id].l == t[id].r) return t[id].mn = val, void(); int mid = (t[id].l + t[id].r) >> 1; if(pos <= mid) modify(ls, pos, val); else modify(rs, pos, val); pushup(id); } inline int query_l(int id, int val){ if(t[id].mn >= val) return 0; if(t[id].l == t[id].r) return t[id].l; if(t[ls].mn < val) return query_l(ls, val); else return query_l(rs, val); } inline int query_r(int id, int val){ if(t[id].mn >= val) return 0; if(t[id].l == t[id].r) return t[id].l; if(t[rs].mn < val) return query_r(rs, val); else return query_r(ls, val); } } ST1, ST2; int main(){ freopen("uphill.in", "r", stdin); freopen("uphill.out", "w", stdout); ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin>>n; for(int i=1; i<=n; ++i) cin>>a[i]; for(int i=1; i<=n; ++i) cin>>b[i]; sort(b+1, b+1+n); ST1.build(1, 1, n); ST2.build(1, 1, n); for(int i=1, pos; i<=n; ++i){ pos = ST1.query_r(1, b[i]); ans[mch[i] = pos] = i; ST1.modify(1, pos, Inf); } for(int i=n, pos; i>=1; --i){ if(mch[i]){ ST1.modify(1, mch[i], a[mch[i]]); pos = ST1.query_l(1, b[i]); ans[mch[i]] = 0; ans[pos] = i; } else { pos = ST2.query_l(1, Inf); if(ans[pos]) mch[ans[pos]] = 0; ans[pos] = i; } ST1.modify(1, pos, Inf), ST2.modify(1, pos, Inf); } for(int i=1; i<=n; ++i) cout<<b[ans[i]]<<' '; return 0; }
本文作者:XiaoLe_MC
本文链接:https://www.cnblogs.com/xiaolemc/p/18563552
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步