暑假集训csp提高模拟11
赛时 rank 9 ,T1 100,T2 100,T3 0,T4 0
update: 赛后T1被hack了,成了99,死因没有记忆化
挂成了rank 10
我又要挂分了。
T3 暴力挂了?
话说jjdw和k8啥时候回来。
T1 Fate
签到题,最短路板子。
考虑一个点
那么考虑对于每一个
记搜一下
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> #include<sys/timeb.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = stdin,*OutFile = stdout; //FILE *ErrFile = stderr; #endif #define pii pair<int,int> #define mk make_pair const int N = 2e5 + 10,mod = 1e9 + 7; struct EDGE{int to,next;}edge[N<<1]; int head[N],cnt; inline void add(int u,int v){edge[++cnt] = {v,head[u]};head[u] = cnt;} priority_queue<pii,vector<pii>,greater<pii> > q; bitset<N> vis; unordered_set<int> pre[N]; int dist[N],num[N]; int n,s,t,m,mn; inline void dijkstra(int s){ vis.reset(); memset(dist,0x3f,sizeof dist); dist[s] = 0;num[s] = 1; queue<int> q;q.push(s);vis[s] = true; while(q.size()){ int x = q.front();q.pop();vis[x] = false; for(int i = head[x]; i;i = edge[i].next){ int y = edge[i].to; if(dist[y] > dist[x] + 1){ dist[y] = dist[x] + 1; num[y] = num[x] % mod; unordered_set<int> ().swap(pre[y]); pre[y].insert(x); if(!vis[y]){ vis[y] = true; q.push(y); } } else if(dist[y] == dist[x] + 1) num[y] = (num[y] + num[x]) % mod,pre[y].insert(x); } } } int ans = 0; int mp[N]; int dfs(int x){ if(vis[x]) return mp[x]; vis[x] = true; int ans = 0; for(int i = head[x]; i;i = edge[i].next){ int y = edge[i].to; if(pre[x].find(y) != pre[x].end()) continue; if(dist[y] == dist[x]) ans = (0ll + ans + num[y]) % mod; } for(auto i : pre[x]) ans = (ans + dfs(i)) % mod; return mp[x] = ans; } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); cin>>n>>m>>s>>t; for(int i = 1,u,v;i <= m; ++i){ cin>>u>>v; add(u,v);add(v,u); } dijkstra(s);; cout<<dfs(t)<<'\n'; }
T2 EVA
贪心。
考虑枚举任意一点为起点,看看其在t时最多可以抓住多少。
用优先队列存一条鱼可以被抓住的起始时间,不能被抓住的终止时间。
然后pop就行
所以这也配蓝?
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); FILE *ErrFile=errfile("err.err"); #else FILE *Infile = stdin,*OutFile = stdout; //FILE *ErrFile = stderr; #endif const int N = 2e3 + 10; const db eps = 1e-9; struct node{int x,v,w;}a[N]; #define mk make_pair int n,s,sum; signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); cin>>n>>s; for(int i = 1;i <= n; ++i) cin>>a[i].w>>a[i].x>>a[i].v; sort(a+1,a+1+n,[](node x,node y){return x.x < y.x;}); int ans = 0; for(int i = 1;i <= n; ++i){ __gnu_pbds::priority_queue<pair<db,int>,greater<pair<db,int> > > add; __gnu_pbds::priority_queue<pair<db,int>,greater<pair<db,int> > > del; // cerr<<i<<":\n"; int res = a[i].w;//算上自己 for(int j = 1;j <= n; ++j){ if(i == j) continue; if(j < i){ if(a[j].v <= a[i].v && a[j].x != a[i].x) continue;//在后面还无法超过 else if(a[j].v == a[i].v && a[j].x == a[i].x){res += a[j].w;continue;}//在一起 else if(a[j].v < a[i].v && a[j].x < a[i].x) continue; else if(a[j].v < a[i].v && a[j].x == a[i].x){ db reach = 1.0 * (a[i].x - a[j].x)/(a[j].v - a[i].v); add.push(mk(reach,j)); del.push(mk(reach,j)); continue; } db reach = 1.0 * (a[i].x - a[j].x)/(a[j].v - a[i].v);//可以捉到 db de = 1.0 * (a[i].x + s - a[j].x)/(a[j].v - a[i].v);//最后可以捉到的时间 add.push(mk(reach,j)),del.push(mk(de,j)); } if(j > i){ if(a[j].v >= a[i].v && a[i].x + s < a[j].x) continue;//无法捉到 else if(a[j].v == a[i].v && a[i].x + s >= a[j].x){res += a[j].w;continue;}//一直可以捉到 if(a[i].v > a[j].v){ db reach = 1.0 * (a[j].x - a[i].x - s)/(a[i].v - a[j].v); db de = 1.0 * (a[j].x - a[i].x) / (a[i].v - a[j].v); add.push(mk(reach,j)); del.push(mk(de,j)); } else{ db reach = 0.0; db de = 1.0 * (a[i].x + s - a[j].x)/(a[j].v - a[i].v); add.push(mk(max(reach,0.0),j)); del.push(mk(de,j)); } } } ans = max(ans,res); while(add.size()){ db now = add.top().first;res += a[add.top().second].w; add.pop(); while(del.size() && del.top().first + eps < now){ res -= a[del.top().second].w; del.pop(); } ans = max(ans,res); } } cout<<ans<<'\n'; }
T3 嘉然登场
来自int_R的思路
考虑将所有的数分为两种
将一个
从大到小放所有
放第一类数
除以重复元素出现次数的阶乘。
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = stdin,*OutFile = stdout; //FILE *ErrFile = stderr; #endif const int N = 2e5 + 10,mod = 998244353; int n,k,a[N],cnt[N]; inline ll power(ll a,ll b,ll mod){ ll res = 1; for(; b;b >>= 1,a = a * a % mod) if(b&1) res = res * a % mod; return res; } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); cin>>n>>k; for(int i = 1;i <= n; ++i) cin>>a[i]; sort(a+1,a+1+n); if(a[n] + a[1] < k) return cout<<0<<'\n',0; for(int i = 1;i <= n && a[i] <= (k-1)/2; ++i){ ++cnt[lower_bound(a+1,a+1+n,k-a[i])-a]; } ll ans = 1,pos_num = 1,total = 1; for(int i = n;i && a[i] > (k-1)/2; --i){ ans = ans * pos_num % mod,++pos_num; for(int j = 1;j <= cnt[i];++j) ans = ans * pos_num % mod,--pos_num; } for(int i = 1,j = 1;i <= n; i = j){ while(a[j] == a[i]) ++j; for(int k = 1;k <= j-i; ++k) total = total * k % mod; } cout<<ans * power(total,mod-2,mod)%mod; }
T4 Clannad
P9340 [JOISC 2023 Day3] Tourism
赛时想了一个bitset的做法,但是莫名WA了。
套路题
考虑如何计算点集。我们用数据结构标记一下所有被查询的点走到某一个特殊点所经过的边,统计被标记的边的数量。
我们钦定这个特殊点为1,记
考虑如何统计答案。
离线,按r排序,以时间为值进行覆盖。统计
但是如果只覆盖到
用一个BIT统计值域,ODT区间赋值。
其实还有bitset和回滚莫队的做法,但我不会……
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = stdin,*OutFile = stdout; //FILE *ErrFile = stderr; #endif const int N = 1e5 + 10; int n,m,q,a[N],st[18][N],ans[N];; struct Query{int l,r,id;}Q[N]; struct EDGE{int to,next;}edge[N<<1]; int head[N],cnt; inline void add(int u,int v){edge[++cnt] = {v,head[u]};head[u] = cnt;} namespace TCS{ int fa[N],dep[N],top[N],siz[N],son[N],dfn[N],tot; void dfs1(int x){ siz[x] = 1; dep[x] = dep[fa[x]] + 1; for(int i = head[x]; i;i = edge[i].next){ int y = edge[i].to; if(y == fa[x]) continue; fa[y] = x;dfs1(y); siz[x] += siz[y]; if(siz[son[x]] < siz[y]) son[x] = y; } } void dfs2(int x,int t){ top[x] = t; dfn[x] = ++tot; if(son[x]) dfs2(son[x],t);else return; for(int i = head[x]; i;i = edge[i].next){ int y = edge[i].to; if(y == son[x] || y == fa[x]) continue; dfs2(y,y); } } inline int LCA(int x,int y){ int fx = top[x],fy = top[y]; while(fx != fy){ if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y); x = fa[fx]; fx = top[x]; } if(dep[x] > dep[y]) swap(x,y); return x; } }using namespace TCS; class BIT{ private: int tree[N]; #define lowbit(x) (x&(-x)) public: int mx; inline void update(int pos,int val){ for(int i = pos;i <= mx;i += lowbit(i)) tree[i] += val; } inline int query(int pos){ int res = 0; for(int i = pos; i;i -= lowbit(i)) res += tree[i]; return res; } }T; class ODT{ private: struct node{ int l,r;mutable int val; inline bool operator < (const node &a) const {return l < a.l;} node (int L = 0,int R = 0,int Val = 0) : l(L),r(R),val(Val){} }; #define sit set<node>::iterator public: set<node> s; inline sit split(int pos){ sit it = s.lower_bound(node(pos)); if(it != s.end() && it->l == pos) return it; --it; int l = it->l,r = it->r,val = it->val; s.erase(it); s.insert(node(l,pos-1,val)); return s.insert(node(pos,r,val)).first; } inline void assign(int l,int r,int val){ sit it2 = split(r + 1),it1 = split(l); for(sit it = it1;it != it2; ++it) T.update(m-it->val+1,-(it->r-it->l+1)); s.erase(it1,it2); s.insert(node(l,r,val)); T.update(m-val+1,r-l+1); } inline void insert(int l,int r,int val){s.insert(node(l,r,val));} }Tree; inline void update(int x,int val){ while(x){ Tree.assign(dfn[top[x]],dfn[x],val); x = fa[top[x]]; } } inline void pre(){ int t = log2(m)+1; for(int i = 1;i <= m; ++i) st[0][i] = a[i]; for(int j = 1;j <= t; ++j){ for(int i = 1;i + (1<<j) - 1 <= m; ++i){ st[j][i] = LCA(st[j-1][i],st[j-1][i+(1<<(j-1))]); } } } inline int query(int l,int r){ int k = log2(r-l+1); return LCA(st[k][l],st[k][r-(1<<k)+1]); } vector<int> vec[N]; signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); cin>>n>>m>>q;Tree.insert(1,n,0);T.mx = m; for(int i = 1,u,v;i < n; ++i) cin>>u>>v,add(u,v),add(v,u); for(int i = 1;i <= m; ++i) cin>>a[i]; dfs1(1);dfs2(1,1);pre(); for(int i = 1;i <= q; ++i){ cin>>Q[i].l>>Q[i].r;Q[i].id = i; vec[Q[i].r].push_back(i); ans[i] = -dep[query(Q[i].l,Q[i].r)] + dep[1]; } for(int i = 1;i <= m; ++i){ update(a[i],i); for(int j : vec[i]) ans[j] += T.query(m-Q[j].l+1); } for(int i = 1;i <= q; ++i) cout<<ans[i]<<'\n'; }
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18330832
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】