CSP模拟 小 trick 总结 (持续施工中)
虽然这篇博客来的有点晚,但还是写了,欢迎dalao补充(
(很杂,建议先浏览目录)
1、分块、莫队有关:
----例题:洛谷 P3709
MAN
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define fi first #define se second #define ps push_back #define mk make_pair #define rint register int #define G cout<<"-------------------"<<endl inline ll read(){ char c=getchar();ll x=0,f=1; while(!isdigit(c))(c=='-'?f=-1:0),c=getchar(); while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } const int N=2e5+3,inf=0x7fffffff; const ll linf=0x3f7f7f7f7f7f7f7f,mod=1e9+7; int n,a[N],cnt[N],b[N],ans,anss[N],m,zh[N],cntp,len,st[N],ed[N]; struct jj{ int l,r,id; inline bool operator <(const jj&x)const{ if(zh[l]==zh[x.l])return r<x.r; return zh[l]<zh[x.l]; } }q[N]; int main(){ // #ifndef ONLINE_JUDGE // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); // #endif ios::sync_with_stdio(0);cin.tie(0),cout.tie(0); n=read(),m=read(); len=pow(n,0.5),cntp=n/len; for(int i=1;i<=cntp;++i){ st[i]=ed[i-1]+1,ed[i]=ed[i-1]+len,ed[cntp]=n; for(int j=st[i];j<=ed[i];++j) zh[j]=i; } for(int i=1;i<=n;++i) b[i]=a[i]=read(); sort(b+1,b+1+n); int n1=unique(b+1,b+1+n)-b-1; for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+n1,a[i])-b; for(int i=1,l,r;i<=m;++i){ l=read(),r=read();q[i]={l,r,i}; } sort(q+1,q+1+m); int l1=0,r1=0;int la=0; for(int i=1,l,r;i<=m;++i){ // cout<<i<<endl;/ l=q[i].l,r=q[i].r; if(zh[l]==zh[r]){ fill(cnt+1,cnt+1+n1,0);ans=0; for(int j=l;j<=r;++j) ans=max(ans,++cnt[a[j]]); anss[q[i].id]=ans; continue; } if(zh[l]!=zh[q[i-1].l]||zh[q[i-1].l]==zh[q[i-1].r]){ fill(cnt+1,cnt+1+n1,0); l1=ed[zh[l]],r1=l1-1;ans=la=0; } while(r1<r)ans=max(ans,++cnt[a[++r1]]); // memcpy(zan,cnt,4*(n1+1)); la=ans; while(l1>l)ans=max(ans,++cnt[a[--l1]]); anss[q[i].id]=ans; ans=la;while(l1<ed[zh[l]])--cnt[a[l1++]]; } for(int i=1;i<=m;++i) cout<<-anss[i]<<'\n'; }
2、分治有关:
CDQ 初学的话推荐一个博客:mlystdcall
毒瘤 ,可以离线的话,那么就可以用cdq,
1、CDQ 优化 DP:
inline void cdq(int l,int r){ if(l==r)return; int mid=l+r>>1; cdq(l,mid),cdq(mid+1,r); /* luangao */ }
inline void cdq(int l,int r){ if(l==r)return; int mid=l+r>>1; cdq(l,mid); sort(q+l,q+mid+1,cmp);sort(q+mid+1,q+r+1,cmp);//别忘了进行排序 /* luangao */ cdq(mid+1,r); }
P5621
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define fi first #define se second #define ps push_back #define mk make_pair #define rint register int #define G cout<<"-------------------"<<endl inline ll read(){ char c=getchar();ll x=0,f=1; while(!isdigit(c))(c=='-'?f=-1:0),c=getchar(); while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define int ll const int N=1e6+10,inf=0x7fffffff,B=1e5+1,BB=B<<1; const ll linf=0x3f7f7f7f7f7f7f7f,mod=1e9+7; ll f[N],w[N]; int n; struct BIT{ ll c[BB]; inline void add(int x,ll y){ while(x<BB) c[x]=max(c[x],y),x+=x&-x; } inline ll ask(int x){ ll ans=-linf; while(x) ans=max(ans,c[x]),x^=x&-x; return ans; } inline void clear(int x){ while(x<BB) c[x]=-linf,x+=x&-x; } }T; struct jj{ int a,b,c,d,op,id; }q[N],tp[N],tpp[N]; inline bool cmpb(const jj&x,const jj&y){ if(x.b!=y.b)return x.b<y.b; if(x.c!=y.c)return x.c<y.c; if(x.d!=y.d)return x.d<y.d; if(x.a!=y.a)return x.a<y.a; return w[x.id]>w[y.id]; } inline bool cmpa(const jj&x,const jj&y){ if(x.a!=y.a)return x.a<y.a; if(x.b!=y.b)return x.b<y.b; if(x.c!=y.c)return x.c<y.c; if(x.d!=y.d)return x.d<y.d; return w[x.id]>w[y.id]; } inline bool cmpc(const jj&x,const jj&y){ if(x.c!=y.c)return x.c<y.c; if(x.d!=y.d)return x.d<y.d; if(x.a!=y.a)return x.a<y.a; if(x.b!=y.b)return x.b<y.b; return w[x.id]>w[y.id]; } inline void man(int l,int r){ if(l==r)return; int mid=l+r>>1; man(l,mid); for(int i=l;i<=r;++i) tpp[i]=tp[i]; stable_sort(tpp+l,tpp+mid+1,cmpc); stable_sort(tpp+mid+1,tpp+r+1,cmpc); for(int j=mid+1,i=l;j<=r;++j){ while(i<=mid&&tpp[i].c<=tpp[j].c){ if(!tpp[i].op)T.add(tpp[i].d,f[tpp[i].id]); ++i; } if(tpp[j].op)f[tpp[j].id]=max(f[tpp[j].id],T.ask(tpp[j].d)+w[tpp[j].id]); } for(int i=l;i<=mid;++i) T.clear(tpp[i].d); man(mid+1,r); } inline void cdq(int l,int r){ if(l==r)return; int mid=l+r>>1; cdq(l,mid); for(int i=l;i<=r;++i) tp[i]=q[i],tp[i].op=(i>mid); stable_sort(tp+l,tp+r+1,cmpb); man(l,r); cdq(mid+1,r); } main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif ios::sync_with_stdio(0);cin.tie(0),cout.tie(0); n=read(); memset(T.c,0xcf,sizeof(T.c)); for(int i=1,a,b,c,d,z;i<=n;++i){ a=read()+B,b=read()+B,c=read()+B,d=read()+B,z=read();q[i]={a,b,c,d,0,i};f[i]=z;w[i]=z; } stable_sort(q+1,q+1+n,cmpa); cdq(1,n); for(int i=2;i<=n;++i) f[1]=max(f[1],f[i]); cout<<f[1]; }
2、CDQ 排序:
反正我是被卡死过很多次。
3、最短路及其优化:
(感谢 帮忙指出错误,提出建议)
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define fi first #define se second #define ps push_back #define mk make_pair #define rint register int #define G cout<<"-------------------"<<endl inline ll read(){ char c=getchar();ll x=0,f=1; while(!isdigit(c))(c=='-'?f=-1:0),c=getchar(); while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } const int N=2e5+10,inf=0x7fffffff; const ll linf=0x3f7f7f7f7f7f7f7f,mod=1e9+7; ll v[N]; ll n,hd[N],cnt,m,dis[N]; struct jj{ int fr,to,next;ll w; }bi[N<<1]; inline void add(int x,int y,ll z){ bi[++cnt]={x,y,hd[x],z+v[y]},hd[x]=cnt; bi[++cnt]={y,x,hd[y],z+v[x]},hd[y]=cnt; } bool vis[N]; signed main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif n=read(),m=read(); for(int i=1;i<=n;++i) v[i]=read(); ll x,y,z; for(int i=1;i<=m;++i){ x=read(),y=read(),z=read(); add(x,y,z); } memset(dis,0x3f,sizeof(dis)); priority_queue<pair<ll,int> >q; dis[1]=0;q.push({0,1}); for(int p=1;p<=n&&!q.empty();++p){ int k=q.top().se;q.pop(); if(vis[k]){//无效的取值 --p;continue; } vis[k]=1; for(int i=hd[k];i;i=bi[i].next){ int j=bi[i].to; if(vis[j])continue; if(dis[j]>dis[k]+bi[i].w){ dis[j]=dis[k]+bi[i].w,q.push({-dis[j],j}); } } } for(int i=2;i<=n;++i) printf("%lld ",dis[i]+v[1]); }
没有打码,粘个雪张的过来
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<cmath> inline int read(){ int x=0,fh=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') fh=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*fh; } const int maxn=2e5+5; int t,head[maxn],tot=2,n,m,cnt,qd,zd; struct asd{ int to,next,val; }b[maxn]; void ad(int aa,int bb,int cc){ b[tot].to=bb; b[tot].next=head[aa]; b[tot].val=cc; head[aa]=tot++; } struct jie{ int num,jl; jie(){} jie(int aa,int bb){ num=aa,jl=bb; } bool operator < (const jie& A)const{ return jl>A.jl; } }; bool vis[maxn]; int dis[maxn]; void dij(int qd){ std::priority_queue<jie> q; memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[qd]=0; q.push(jie(qd,0)); while(!q.empty()){ int now=q.top().num; q.pop(); if(now==zd) return; if(vis[now]) continue; vis[now]=1; for(int i=head[now];i!=-1;i=b[i].next){ int u=b[i].to; if(dis[u]>dis[now]+b[i].val){ dis[u]=dis[now]+b[i].val; q.push(jie(u,dis[u])); } } } } struct jl{ int bh,jz; jl(){} jl(int aa,int bb){ bh=aa,jz=bb; } }c[maxn]; int main(){ freopen("leave.in","r",stdin); freopen("leave.out","w",stdout); t=read(); while(t--){ memset(head,-1,sizeof(head)); memset(&b,0,sizeof(b)); memset(&c,0,sizeof(c)); tot=2,cnt=0; n=read(),m=read(); for(int i=1;i<=m;i++){ int aa,bb,cc; aa=read(),bb=read(),cc=read(); if(aa>bb) std::swap(aa,bb); if(aa==1) c[++cnt]=jl(bb,cc); else { ad(aa,bb,cc); ad(bb,aa,cc); } } int nans=0x3f3f3f3f,nn=n; for(int i=1;i<=n;i<<=1){ qd=++nn,zd=++nn; for(int j=1;j<=cnt;j++){ if(c[j].bh&i) ad(qd,c[j].bh,c[j].jz); else ad(c[j].bh,zd,c[j].jz); } dij(qd); nans=std::min(nans,dis[zd]); } if(nans==0x3f3f3f3f) printf("-1\n"); else printf("%d\n",nans); } return 0; }
给了一些注释
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; #define fi first #define se second #define ps push_back #define mk make_pair #define rint register int #define G cout<<"-------------------"<<endl inline ll read(){ char c=getchar();ll x=0,f=1; while(!isdigit(c))(c=='-'?f=-1:0),c=getchar(); while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } const int N=1e6+10,inf=0x3f3f3f3f; const ll linf=0x3f7f7f7f7f7f7f7f,mod=1e9+7; int n,m,cnt,hd[N],disp[N]; struct jj{ int to,next,w; }bi[N]; pii dis[N]; bool vis[N]; inline void add(int x,int y,int z){bi[++cnt]={y,hd[x],z},hd[x]=cnt,bi[++cnt]={x,hd[y],z},hd[y]=cnt;} inline void dij(int x){ // G;G;G; fill(dis+1,dis+1+n,mk(inf,0));//pair 类型的 dis,first存权值,second存源边 fill(disp+1,disp+1+n,inf);// 合法的(不走源边)的最短路 priority_queue<pair<pii,int> > q; for(int i=hd[x];i;i=bi[i].next){ int j=bi[i].to; dis[j].fi=min(dis[j].fi,bi[i].w);dis[j].se=i,q.push({{-dis[j].fi,dis[j].se},j});//将 1 的边权赋给各个点 } while(!q.empty()){ int k=q.top().se;q.pop(); for(int i=hd[k];i;i=bi[i].next){ if(i==(dis[k].se^1))continue;// 和源边是一条边,不能走 int j=bi[i].to; if(dis[j].fi>dis[k].fi+bi[i].w){// 更新最短路 dis[j]={dis[k].fi+bi[i].w,dis[k].se};q.push({{-dis[j].fi,dis[j].se},j}); } if(dis[j].se!=dis[k].se){// 用最短路更新次短路 if(disp[j]>dis[k].fi+bi[i].w) disp[j]=dis[k].fi+bi[i].w,q.push({{-dis[j].fi,dis[j].se},j}); } if(disp[j]>disp[k]+bi[i].w)// 用次短路更新次短路 disp[j]=disp[k]+bi[i].w,q.push({{-dis[j].fi,dis[j].se},j}); } } int ans=1e9; for(int i=hd[x];i;i=bi[i].next){ int j=bi[i].to; ans=min(ans,disp[j]+dis[j].fi); } ans=min(ans,dis[x].fi);// 自己走到了 1 的最短路 cout<<(ans==1e9?-1:ans)<<'\n'; } int main(){ // #ifndef ONLINE_JUDGE // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); // #endif ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=read(); while(t--){ n=read(),m=read(); fill(hd+1,hd+1+n,0);cnt=1; for(int i=1,x,y,z;i<=m;++i){ x=read(),y=read(),z=read(); add(x,y,z); } // cout<<1<<endl; dij(1); } }
4、杂项 trick
(1)正难则反类:
(2)合理利用题目数据范围:
(3)异或哈希:
map[x]=(ll)rand()+rand();
暂时只有这些,会持续施工。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)