多校A层冲刺NOIP2024模拟赛07
rank 7,T1 100pts,T2 0pts,T3 70pts,T4 16pts
accoder上rank31,同分
限速(speed)
签,糖。
打的
考虑分类讨论,有两种情况。
-
最大值是由最小的转化过来的,那么就是看边权
的是否可以构成一颗最大生成树,时间复杂度 -
最大值是由更大的减下来的,发现如果小的可以,那么大的也可以,答案具有单调性,考虑二分答案。假设当前二分到的答案为
,那么 表示可否使用边权 的构成一个生成树。但这个生成树必须强制将边权 的最大的边加入进去,剩下的跑最小生成树,然后记录该生成树需要的边,如果有边权 ,那么答案
最后答案取min,时间复杂度
然而事实是只需要求最小生成树和边权
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(#x".in","r",stdin) #define outfile(x) freopen(#x".out","w",stdout) #define errfile(x) freopen(#x".err","w",stderr) #define ansfile(x) freopen(#x".ans","w",stdout) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile(in),*OutFile = outfile(out); // FILE *ErrFile = errfile(err); #else FILE *Infile = infile(speed),*OutFile = outfile(speed); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #define int long long const int N = 2e5 + 10,M = 2e5 + 10,inf = 0x3f3f3f3f3f3f3f3f; int fa[N],n,m,k,ans = inf; struct node{ int u,v,w; bool operator < (node x) const{return w < x.w;} }e[M]; int get_fa(int x){return x==fa[x]?x:fa[x] = get_fa(fa[x]);} bitset<N> vis; inline bool check1(int mid){ rep(i,1,n,1) fa[i] = i; rep(i,1,m,1) vis[i] = false; int pos = upper_bound(e+1,e+1+m,node{0,0,mid}) - e - 1; drep(i,pos,1,1){ int fx = get_fa(e[i].u),fy = get_fa(e[i].v); if(fx == fy) continue; fa[fx] = fy; vis[i] = true; } rep(i,2,n,1) if(get_fa(i) != get_fa(i-1)) return false; return true; } inline void get_ans1(int l,int r){ bool flag = check1(k); int pos = upper_bound(e+1,e+1+m,node{0,0,k}) - e - 1,res = inf; if(!flag) return; drep(i,pos,1,1){if(vis[i]){res = e[i].w;break;}} ans = min(ans,abs(res-k)); } inline bool check2(int mid){ rep(i,1,n,1) fa[i] = i; rep(i,1,m,1) vis[i] = false; int pos = upper_bound(e+1,e+1+m,node{0,0,mid}) - e - 1; int fx = get_fa(e[pos].u),fy = get_fa(e[pos].v); if(fx != fy) fa[fx] = fy,vis[pos] = true; rep(i,1,pos-1,1){ int fx = get_fa(e[i].u),fy = get_fa(e[i].v); if(fx == fy) continue; fa[fx] = fy; vis[i] = true; } rep(i,2,n,1) if(get_fa(i) != get_fa(i-1)) return false; return true; } inline void get_ans2(int l,int r){ if(l > r) return; int res = -inf; while(l <= r){ int mid = (l + r) >> 1; if(check2(mid)) res = mid,r = mid - 1; else l = mid + 1; } int emm = 0; int pos = upper_bound(e+1,e+1+m,node{0,0,res}) - e - 1; if(res == -inf) emm = inf; if(res != -inf) check2(res); drep(i,pos,1,1){ if(e[i].w <= k) break; if(!vis[i]) continue; emm += abs(k-e[i].w); } ans = min(ans,emm); } inline void solve(){ cin>>n>>m>>k; rep(i,1,m,1) cin>>e[i].u>>e[i].v>>e[i].w; sort(e+1,e+1+m,[](node x,node y){return x.w < y.w;}); get_ans1(0,k);get_ans2(k+1,e[m].w); cout<<ans<<'\n'; } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
酒鬼 (drunkard)
赛时题没看懂,部分分不会打。
大力分讨加大模拟,牛魔题。
考虑到合法状态与
但是发现当
然后用一个
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(#x".in","r",stdin) #define outfile(x) freopen(#x".out","w",stdout) #define errfile(x) freopen(#x".err","w",stderr) #define ansfile(x) freopen(#x".ans","w",stdout) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile(in),*OutFile = outfile(out); // FILE *ErrFile = errfile(err); #else FILE *Infile = infile(drunkard),*OutFile = outfile(drunkard); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; const int inf = 0x3f3f3f3f; int n,m,nmn = 0,nmx = inf; bool flag = true; #define pii pair<int,int> #define mk make_pair map<ll,pii> mp; inline bool check(pii p1,pii p2){ if(abs(p2.first - p1.first) > p2.second - p1.second) return false; if(p1.first != 1 && p1.second <= nmn) return false; if(p2.first != 1) nmx = min(nmx,p2.second - p2.first + 1); if(p1.first == 1 && p1.second <= nmx){ if((abs(p2.first - p1.first)&1) != ((p2.second-p1.second)&1)) nmn = max(nmn,p1.second + 1); return true; } if((abs(p2.first - p1.first)&1) != ((p2.second - p1.second)&1)) return false; return true; } inline void solve(){ cin>>n>>m; mp[0] = mk(1,0); rep(test,1,m,1){ string op;cin>>op; if(op[1] == 'l'){ int p,q;cin>>p>>q; if(!flag) continue; auto it = mp.find(q); if(it != mp.end()){ if(it->second.first != p) flag = false; continue; } it = mp.lower_bound(q); if(it != mp.end() && !check(mk(p,q),it->second)){flag = false;continue;} it--; if(!check(it->second,mk(p,q))) {flag = false;continue;} mp[q] = mk(p,q); } if(op[1] == 'i'){ if(!flag){cout<<"bad\n";continue;} cout<<nmn<<'\n'; } if(op[1] == 'a'){ if(!flag){cout<<"bad\n";continue;} if(nmx == inf) cout<<"inf\n"; else cout<<nmx<<'\n'; } } } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
距离(distance)
赛时打的
有一个性质
然后就变成了维护
发现
最后答案要乘上二,因为反过来还有一个。
时间复杂度
fhq_treap也可以维护,也是
DSU On Tree也可以,但DSU On Tree比较慢,是
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(#x".in","r",stdin) #define outfile(x) freopen(#x".out","w",stdout) #define errfile(x) freopen(#x".err","w",stderr) #define ansfile(x) freopen(#x".ans","w",stdout) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile(in),*OutFile = outfile(out); // FILE *ErrFile = errfile(err); #else FILE *Infile = infile(distance),*OutFile = outfile(distance); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; #define eb emplace_back #define All(x) x.begin(),x.end() namespace IO{ char buf[1<<23],*p1,*p2; #define gc() (p1==p2&&(p2=(p1=buf)+fread_unlocked(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++) #define pc putchar_unlocked template<class T> inline void read(T &x){ x = 0; char s = gc(); for(;s < '0' || s > '9';s = gc()); for(;'0' <= s && s <= '9';s = gc()) x = (x<<1)+(x<<3)+(s^48); } template<class T,class... Args> inline void read(T &x,Args&... argc){read(x);read(argc...);} template<class T> inline void write(T x){ static int sta[20],top = 0; do{sta[++top] = x%10,x /= 10;}while(x); do{pc(sta[top--]+'0');}while(top); } inline void write(char x){pc(x);} template<class T,class... Args> inline void write(T x,Args... argc){write(x);write(argc...);} }using namespace IO; const int N = 5e5 + 10,mod = 1e9 + 7; int n,a[5][N],ans[N],np,rt[N]; vector<int> e[N],num[5]; struct Segment_Tree{ struct segment_tree{ int lc,rc,val,sum,ans; #define lc(x) tree[x].lc #define rc(x) tree[x].rc #define val(x) tree[x].val #define sum(x) tree[x].sum #define ans(x) tree[x].ans }tree[N*25]; int tot = 0; inline void P(int k){ sum(k) = sum(lc(k)) + sum(rc(k)); val(k) = (val(lc(k)) + val(rc(k)))%mod; } void I(int &k,int l,int r,int pos,int val){ if(!k) k = ++tot,lc(k) = rc(k) = val(k) = sum(k) = ans(k) = 0; if(l == r) return sum(k)++,val(k) = (val(k) + num[np][val])%mod,void(); int mid = (l + r) >> 1; if(pos <= mid) I(lc(k),l,mid,pos,val); else I(rc(k),mid+1,r,pos,val); P(k); } void Merge(int &x,int y){ if(!x) return x = y,void(); if(!y) return; sum(x) += sum(y); val(x) = (val(x) + val(y))%mod; Merge(lc(x),lc(y));Merge(rc(x),rc(y)); ans(x) = (0ll + ans(lc(x)) + ans(rc(x)) + 1ll*val(rc(x))*sum(lc(x))%mod - 1ll*val(lc(x))*sum(rc(x))%mod + mod)%mod; } }T; inline void pre(int p){ num[p].eb(INT_MIN); rep(i,1,n,1) num[p].eb(a[p][i]); sort(All(num[p])); num[p].erase(unique(All(num[p])),num[p].end()); rep(i,1,n,1) a[p][i] = lower_bound(All(num[p]),a[p][i]) - num[p].begin(); } void dfs(int x,int f){ T.I(rt[x],1,n,a[np][x],a[np][x]); for(int y:e[x]){ if(y == f) continue; dfs(y,x); T.Merge(rt[x],rt[y]); } ans[x] = (ans[x] + T.ans(rt[x]))%mod; } inline void solve(){ read(n); rep(i,2,n,1){int u,v;read(u,v);e[u].eb(v);e[v].eb(u);} rep(i,1,n,1) read(a[1][i],a[2][i]),a[3][i] = a[1][i]+a[2][i],a[4][i] = a[1][i] - a[2][i]; rep(i,1,4,1) pre(i); drep(i,4,1,1){ rep(j,1,n,1) rt[j] = 0; T.tot = 0,np = i;dfs(1,0); if(i == 3) rep(j,1,n,1) ans[j] = (-500000004ll*ans[j]%mod+mod)%mod; } rep(i,1,n,1) write(ans[i]*2%mod,'\n'); } signed main(){solve();}
update:给神卡常卡过了,学习了一个快速取模的Barrett约减。
团队选拔(selection)
赛时打的特殊性质,但好像正解也是线段树合并。
好难不会。
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(#x".in","r",stdin) #define outfile(x) freopen(#x".out","w",stdout) #define errfile(x) freopen(#x".err","w",stderr) #define ansfile(x) freopen(#x".ans","w",stdout) #define rep(i,s,t,p) for(int i = s;i <= t; i += p) #define drep(i,s,t,p) for(int i = s;i >= t; i -= p) #ifdef LOCAL FILE *InFile = infile(in),*OutFile = outfile(out); // FILE *ErrFile = errfile(err); #else FILE *Infile = infile(selection),*OutFile = outfile(selection); //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; const int N = 1e5 + 10,mod = 998244353; int st[18][N],n,a[N],lg[N]; inline void st_pre(){ lg[1] = 0; rep(i,2,n,1) lg[i] = lg[i>>1]+1; int t = lg[n]; rep(i,1,n,1) st[0][i] = a[i]; rep(j,1,t,1) rep(i,1,n-(1<<j)+1,1){ st[j][i] = __gcd(st[j-1][i],st[j-1][i+(1<<(j-1))]); } } inline int Q(int l,int r){ int k = lg[r-l+1]; return __gcd(st[k][l],st[k][r-(1<<k)+1]); } namespace S1{ int b[N],ans = 0,vis[N],f[N],k[N]; inline void get_ans(){ int gcd = 0; bool flag = false; set<int> st; rep(i,1,n,1) k[i] = 0; rep(i,1,n,1){ if(b[i] == 1)gcd = a[i],flag = true,k[i]++; if(!b[i] && vis[i]) st.insert(a[i]),k[i]++; if(b[i] != 1 && flag) gcd = __gcd(gcd,a[i]),k[i]++; if(b[i] == -1){st.insert(gcd);flag = false;} } if(st.size() < 2) rep(i,1,n,1) f[i] += k[i]; } void dfs(int now,bool flag){ if(now == n+1){ if(!flag) return; else get_ans(); return; } b[now] = 0;vis[now] = false; dfs(now+1,flag); b[now] = flag?1:-1; dfs(now+1,flag^1); if(flag) b[now] = 0,vis[now] = true,dfs(now+1,true); } inline void solve(){ dfs(1,true); rep(i,1,n,1) cout<<f[i]<<' '; } } namespace S2{ int f[N],g[N],ans[N]; inline int power(int a,int b,int mod){ int res = 1; for(;b;b >>= 1,a = 1ll*a*a%mod) if(b&1) res = 1ll*res*a%mod; return res; } inline void solve(){ f[1] = g[1] = 1; f[2] = 1,g[2] = 3; rep(i,3,n,1) f[i] = (f[i-1]+f[i-2])%mod, g[i] = (g[i-1]+g[i-2])%mod; ans[1] = 1ll*f[n]*g[n]%mod; rep(i,2,ceil(n/2.0),1) ans[i] = (ans[i-1]+1ll*f[n-(2*(i-1))]*g[n-(2*(i-1))]%mod)%mod; rep(i,n/2+1,n,1) ans[i] = ans[n-i+1]; rep(i,1,n,1) cout<<ans[i]<<' '; } } inline void solve(){ cin>>n; rep(i,1,n,1) cin>>a[i]; // st_pre(); int tot = 0; rep(i,1,n,1) if(a[i] == 1) tot++; if(tot == n) return S2::solve(),void(); return S1::solve(),void(); } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr)->sync_with_stdio(false); solve(); }
挂个官解和std
点此查看代码
#include<bits/stdc++.h> #define LL long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) inline int read() { char c=getchar();int x=0;while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48,c=getchar();return x; } const int mod=998244353,maxn=100005; struct sode{int l,r,v;}st[maxn],bl[maxn]; struct node{int l,r,x,v;}A[maxn*30],B[maxn*30]; struct Seg{int l,r,v;}seg[2][maxn]; int gcd(int a,int b) {return !b?a:gcd(b,a%b);} inline int dqm(int x) {return x<0?x+mod:x;} inline int qm(int x) {return x>=mod?x-mod:x;} inline int cmp(const node &A,const node &B){ return A.v==B.v?A.x<B.x:A.v<B.v; } inline int ctp(const node &A,const node &B) { return A.v==B.v?A.x>B.x:A.v<B.v; } int n,a[maxn],top,sa,sb,lp,sz[2],ans,pre[maxn]; int l[maxn*3],r[maxn*3],tag[maxn*3],d[maxn*3]; inline void pushup(int i) {d[i]=qm(d[i<<1]+d[i<<1|1]);} inline void pushr(int i,int v) { tag[i]=v;d[i]=1ll*(r[i]-l[i]+1)*v%mod; } inline void pushdown(int i) { if(tag[i]==-1) return;pushr(i<<1,tag[i]); pushr(i<<1|1,tag[i]);tag[i]=-1; } void bud(int x,int y,int i) { l[i]=x,r[i]=y,tag[i]=-1;if(x==y) return; int mid=x+y>>1;bud(x,mid,i<<1),bud(mid+1,y,i<<1|1); } void chg(int x,int y,int v,int i) { if(x<=l[i]&&y>=r[i]) {pushr(i,v);return;} int mid=l[i]+r[i]>>1;pushdown(i); if(x<=mid) chg(x,y,v,i<<1); if(y>mid) chg(x,y,v,i<<1|1);pushup(i); } int qry(int x,int y,int i) { if(x<=l[i]&&y>=r[i]) return d[i]; int mid=l[i]+r[i]>>1;pushdown(i); return qm((x<=mid?qry(x,y,i<<1):0)+(y>mid?qry(x,y,i<<1|1):0)); } inline void ins(int l,int r,int v,int o) { if(r>n)r=n;if(l<1)l=1;if(l>r) return; seg[o][++sz[o]]=(Seg){l,r,v}; } inline void calc(int l,int r,int v) { pre[l]=qm(pre[l]+v),pre[r+1]=dqm(pre[r+1]-v); } inline void solve(int L,int R) { int lst=0,v=0;sz[0]=sz[1]=0; for(int i=L;i<=R;++i) { chg(lst,A[i].x-1,v,1); ins(lst+1,A[i].x,qm(v+1),0); lst=A[i].x; v=qm(v+qry(A[i].l-1,A[i].r-1,1)); v=qm(v+A[i].r-A[i].l+1); } chg(lst,n,v,1); ins(lst+1,n+1,qm(v+1),0); lst=n+1,v=0;int rp=lp; while(lp<=sb&&B[lp].v==A[L].v) ++lp; for(int i=rp;i<lp;++i) { chg(B[i].x+1,lst,v,1); ins(B[i].x,lst-1,qm(v+1),1); lst=B[i].x; v=qm(v+qry(B[i].l+1,B[i].r+1,1)); v=qm(v+B[i].r-B[i].l+1); } chg(1,lst,v,1);ans=qm(ans+v); ins(0,lst-1,qm(v+1),1); std::reverse(seg[1],seg[1]+sz[1]+1); int x,y;x=0,y=0; while(x<=sz[0]&&y<=sz[1]) { calc(max(seg[0][x].l,seg[1][y].l),min(seg[0][x].r,seg[1][y].r),dqm(1ll*seg[0][x].v*seg[1][y].v%mod-1)); if(seg[0][x].r<seg[1][y].r) ++x; else if(seg[0][x].r>seg[1][y].r) ++y; else if(seg[0][x].r==seg[1][y].r) ++y,++x; } } int main() { freopen("selection.in", "r", stdin); freopen("selection.out", "w", stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) { for(int j=1;j<=top;++j) st[j].v=gcd(st[j].v,a[i]); st[++top]=(sode){i,i,a[i]}; int tot=0,x=i,y=i; for(int j=top-1;j>=0;--j) { if(st[j].v!=st[j+1].v) { bl[++tot].l=x,bl[tot].r=y; bl[tot].v=st[j+1].v; x=st[j].l,y=st[j].r; }else x=st[j].l; } top=0; while(tot) st[++top]=bl[tot--]; for(int j=1;j<=top;++j) A[++sa]=(node){st[j].l,st[j].r,i,st[j].v}; } top=0; for(int i=n;i;i--) { for(int j=1;j<=top;++j) st[j].v=gcd(st[j].v,a[i]); st[++top]=(sode){i,i,a[i]}; int tot=0,x=i,y=i; for(int j=top-1;j>=0;--j) if(st[j].v!=st[j+1].v) { bl[++tot].l=x,bl[tot].r=y; bl[tot].v=st[j+1].v; x=st[j].l,y=st[j].r; } else y=st[j].r; top=0; while(tot) st[++top]=bl[tot--]; for(int j=1;j<=top;++j) B[++sb]=(node){st[j].l,st[j].r,i,st[j].v}; } std::sort(A+1,A+sa+1,cmp);std::sort(B+1,B+sb+1,ctp); int L=1;lp=1; bud(0,n+1,1); for(int i=2;i<=sa+1;++i) if(A[i].v!=A[i-1].v) solve(L,i-1),L=i; for(int i=1;i<=n;i++)pre[i]=qm(pre[i-1]+pre[i]); for(int i=1;i<=n;i++)printf("%d ",dqm(ans-pre[i])); return 0; }
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18468355
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!