Helloworld,我是来自湖南长沙的一枚蒟蒻,一个普通学生。(还有,我是男生).
从2017年暑假开始,我才接触了c++这种语言,觉得很美妙,有一种无所不能的感觉。
曾经,我只是接触过一部分这一类型的东东,也曾编程制作任务型和对抗型机器人(botball).
希望自己能结合曾经的浅薄知识,对信息学有更深的认识,认真学习!
很乐意交友,很乐意与大家交流学习哦。
以下都是我学到的部分知识,大部分学自他人的博客,真的很感激各路大神。
所以,我也十分乐意分享自己学习算法的理解和心得,希望大家多多关注!(关爱菜鸡,人人有责).
一、
求逆元-费马小定理
#include <bits/stdc++.h> using namespace std; typedef long long lol; int n,p; lol qpow(lol x) { int y=p-2; lol ans=1; while (y) { if (y&1) ans*=x,ans%=p; x*=x;x%=p;y/=2; } return ans; } inline void write(lol x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } int main() { scanf("%d%d",&n,&p); for (int i=1;i<=n;i++) { write(qpow(i)%p); putchar(' '); } return 0; }
二、
树状数组
#include <bits/stdc++.h> using namespace std; typedef long long lol; lol n,m; lol f[500010]; lol lowbit(lol x) { return x&-x; } void add(lol x,lol k) { for (int i=x;i<=n;i+=lowbit(i)) f[i]+=k; } lol getsum(lol x) { lol ans=0; for (int i=x;i;i-=lowbit(i)) ans+=f[i]; return ans; } int main() { cin>>n>>m;lol a; for (int i=1;i<=n;i++) scanf("%lld",&a),add(i,a); lol flag,x,y,k; for (int i=1;i<=m;i++) { scanf("%lld%lld",&flag,&x); if (flag==1) { scanf("%lld",&k); add(x,k); } if (flag==2) { scanf("%lld",&y); printf("%lld ",getsum(y)-getsum(x-1)); } } return 0; }
三、
最大流-Dinic
#include <bits/stdc++.h> using namespace std; int cnt=-1,depth[10010],cur[10010],s,t,n,m; int next[200010],head[10010],v[200010],w[200010]; int dfs(int u,int flow) { if (u==t) return flow; for (int& i=cur[u];i!=-1;i=next[i]) { if ((w[i]!=0)&&(depth[v[i]]==depth[u]+1)) { int di=dfs(v[i],min(flow,w[i])); if (di>0) {w[i]-=di;w[i^1]+=di;return di;} } } return 0; } bool bfs() { queue <int> q; memset(depth,0,sizeof(depth)); while (!q.empty()) q.pop(); q.push(s);depth[s]=1; do { int u=q.front();q.pop(); for (int i=head[u];i!=-1;i=next[i]) { if ((w[i]>0)&&(depth[v[i]]==0)) { q.push(v[i]);depth[v[i]]=depth[u]+1; } } }while(!q.empty()); if (depth[t]>0) return 1; return 0; } int dinic() { int ans=0; while (bfs()) { for (int i=1;i<=n;i++) cur[i]=head[i]; while (int d=dfs(s,3e8)) ans+=d; } return ans; } int main() { int a,b,c; cin>>n>>m>>s>>t; memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); while (m--) { scanf("%d%d%d",&a,&b,&c); cnt++;v[cnt]=b;w[cnt]=c; next[cnt]=head[a];head[a]=cnt; cnt++;v[cnt]=a;w[cnt]=0; next[cnt]=head[b];head[b]=cnt; } cout<<dinic()<<endl; return 0; }
四、
二分图-匈牙利算法
#include <bits/stdc++.h> using namespace std; int n,m,e,girl[1005]; bool used[1005],line[1005][1005]; bool find(int x) { for (int j=1;j<=m;j++) if (line[x][j]&&!used[j]) { used[j]=1; if (!girl[j]||find(girl[j])) { girl[j]=x;return 1; } } return 0; } int main() { int x,y; cin>>n>>m>>e; for (int i=1;i<=e;i++) scanf("%d%d",&x,&y),line[x][y]=1; e=0; for (int i=1;i<=n;i++) { if (find(i)) e++; memset(used,0,sizeof(used)); } cout<<e<<endl; return 0; }
五、
扩展欧几里得
#include <bits/stdc++.h> using namespace std; void exgcd(int a,int b,int &x,int &y) { if (!b) x=1,y=0; else { exgcd(b,a%b,y,x); y-=x*(a/b); } } int main() { int a,b,x,y; cin>>a>>b; exgcd(a,b,x,y); cout<<(x%b+b)%b<<endl; return 0; }
六、
假的字符串Hash,其实是map
#include <bits/stdc++.h> using namespace std; int n; string s; map <string,int> mp; int main() { cin>>n;int ans=0; for (int i=1;i<=n;i++) { cin>>s; if (!mp.count(s)) ans++,mp[s]=1; } cout<<ans<<endl; return 0; }
七、
克鲁斯卡尔
#include <bits/stdc++.h> using namespace std; int n,m; int fa[5001]; struct ed { int f,t,w; }e[400010]; bool cmp(ed a,ed b) { return a.w<b.w; } void init() { for (int i=1;i<=n;i++) fa[i]=i; } int find(int a) { if (a==fa[a]) return a; return fa[a]=find(fa[a]); } void unionset(int a,int b) { int u=find(a),v=find(b); if (u!=v) fa[u]=v; } bool same(int u,int v) { return find(u)==find(v); } void kruskal() { int res=0; init();int cnt=0; sort(e+1,e+1+m,cmp); for (int i=1;i<=m;i++) { if (!same(e[i].f,e[i].t)) { res+=e[i].w; unionset(e[i].f,e[i].t); ++cnt; } if (cnt==n-1) break; } cout<<res<<endl; } int main() { cin>>n>>m;int x,y,w; for (int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&w); e[i].f=x;e[i].t=y;e[i].w=w; } kruskal(); return 0; }
八、
LCA-倍增
#include <bits/stdc++.h> using namespace std; int n,m,ss; int dep[500010]; int dpt[500010][30]; int cnt; int o[1000010]; int s[1000010][2]; void jia(int x,int y) { s[++cnt][1]=o[x]; s[cnt][0]=y;o[x]=cnt; } void dfs(int x,int d) { dep[x]=d; for (int i=o[x];i;i=s[i][1]) { int y=s[i][0]; if (!dep[y]) { dpt[y][0]=x; dfs(y,d+1); } } } void init() { for (int j=1;j<=19;j++) for (int i=1;i<=n;i++) dpt[i][j]=dpt[dpt[i][j-1]][j-1]; } int lca(int a,int b) { if (dep[a]<dep[b]) swap(a,b); for (int j=19;j>=0;j--) if (dep[a]-(1<<j)>=dep[b]) a=dpt[a][j]; if (a!=b) { for (int j=19;j>=0;j--) if (dpt[a][j]!=dpt[b][j]) a=dpt[a][j],b=dpt[b][j]; a=dpt[a][0]; } return a; } int main() { int x,y; cin>>n>>m>>ss; for (int i=1;i<n;i++) { scanf("%d%d",&x,&y); jia(x,y);jia(y,x); } dfs(ss,1);init(); for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); printf("%d ",lca(x,y)); } return 0; }
九、
最长公共子序列(离散+LIS法求LCS)
#include <bits/stdc++.h> #define N 100010 using namespace std; int len,b[N],f[N]; int n,table[N],in[N]; int main() { int a; cin>>n; for (int i=1;i<=n;i++) { scanf("%d",&a); table[a]=i; } for (int i=1;i<=n;i++) scanf("%d",&in[i]); for (int i=1;i<=n;i++) { if (table[in[i]]>b[len]) { b[++len]=table[in[i]]; f[i]=len; continue; } int arr=lower_bound(b+1,b+1+len,table[in[i]])-b; b[arr]=table[in[i]]; f[i]=arr; } cout<<len<<endl; return 0; }
十、
归并排序求逆序对
#include <bits/stdc++.h> using namespace std; int ans,n,a[100010],r[100010]; void msort_nxd(int s,int t) { if (s==t) return; int mid=s+t>>1; msort_nxd(s,mid); msort_nxd(mid+1,t); int i=s,j=mid+1,k=s; while (i<=mid&&j<=t) { if (a[i]<=a[j]) { r[k]=a[i];i++;k++; } else { r[k]=a[j];j++;k++; ans+=mid-i+1; } } while (i<=mid) r[k++]=a[i++]; while (j<=t) r[k++]=a[j++]; for (int q=s;q<=t;q++) a[q]=r[q]; } int main() { cin>>n; for (int i=1;i<=n;i++) { scanf("%d",&a[i]); } msort_nxd(1,n); cout<<ans<<endl; return 0; }
十一、
线段树
#include <bits/stdc++.h> #define ll(x) ((x)<<1) #define rr(x) ((x)<<1|1) using namespace std; typedef long long lol; lol n,m,a[100010]; lol sgm[100010*4],lazy[100010*4]; void shang(lol r) { sgm[r]=sgm[ll(r)]+sgm[rr(r)]; } void xia(lol r,lol z,lol y) { int k=z+y>>1; lazy[ll(r)]+=lazy[r]; lazy[rr(r)]+=lazy[r]; sgm[ll(r)]+=(k-z+1)*lazy[r]; sgm[rr(r)]+=(y-k)*lazy[r]; lazy[r]=0; } void js(lol r,lol z,lol y) { if (z==y) { sgm[r]=a[z]; return; } int k=z+y>>1; js(ll(r),z,k); js(rr(r),k+1,y); shang(r); } void qjxg(lol r,lol z,lol y,lol zz,lol yy,lol v) { if (z>yy||y<zz) return; if (z>=zz&&y<=yy) { lazy[r]+=v; sgm[r]+=(y-z+1)*v; return; } if (lazy[r]) xia(r,z,y); int k=z+y>>1; if (zz<=k) qjxg(ll(r),z,k,zz,yy,v); if (yy>k) qjxg(rr(r),k+1,y,zz,yy,v); shang(r); } lol cx(lol r,lol z,lol y,lol zz,lol yy) { if (z>yy||y<zz) return 0; if (z>=zz&&y<=yy) return sgm[r]; int k=z+y>>1; if (lazy[r]) xia(r,z,y); return cx(ll(r),z,k,zz,yy)+cx(rr(r),k+1,y,zz,yy); } int main() { cin>>n>>m; for (int i=1;i<=n;i++) { scanf("%lld",&a[i]); } js(1,1,n); lol flag,x,y,k; for (int i=1;i<=m;i++) { scanf("%lld",&flag); if (flag==1) { scanf("%lld%lld%lld",&x,&y,&k); qjxg(1,1,n,x,y,k); } else { scanf("%lld%lld",&x,&y); cout<<cx(1,1,n,x,y)<<endl; } } return 0; }
十二、
SPFA
#include <bits/stdc++.h> using namespace std; int n,m,st,d[10010]; int cnt; int o[500010]; int s[500010][3]; void jia(int x,int y,int c) { s[++cnt][1]=o[x]; s[cnt][0]=y; s[cnt][2]=c;o[x]=cnt; } queue <int> q; bool v[10010]; void SPFA() { for (int i=1;i<=n;i++) d[i]=2147483647; v[st]=1;q.push(st);d[st]=0; while (!q.empty()) { int x=q.front(); for (int i=o[x];i;i=s[i][1]) { int y=s[i][0]; if (d[y]>d[x]+s[i][2]) { d[y]=d[x]+s[i][2]; if (!v[y]) { v[y]=1; q.push(y); } } } q.pop();v[x]=0; } } int main() { int x,y,c; cin>>n>>m>>st; for (int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&c); jia(x,y,c); } SPFA(); for (int i=1;i<=n;i++) { printf("%d ",d[i]); } cout<<endl; return 0; }
十三、
树链剖分
#include <bits/stdc++.h> #define ll(x) ((x)<<1) #define rr(x) ((x)<<1|1) using namespace std; typedef long long l; const int N=100010;l n,m,r,p,cnt,dfscnt; l d[N],id[N],f[N],son[N],top[N],siz[N],sgm[N*4],lazy[N*4],a[N],w[N],o[N],s[N*2][2]; void jia(l x,l y) {s[++cnt][1]=o[x];s[cnt][0]=y;o[x]=cnt;} void dfs(l x,l fa,l dep) { f[x]=fa;d[x]=dep;siz[x]=1;l mm=-1; for (int i=o[x];i;i=s[i][1]) { if (s[i][0]!=fa) { dfs(s[i][0],x,dep+1);siz[x]+=siz[s[i][0]]; if (siz[s[i][0]]>mm) son[x]=s[i][0],mm=siz[s[i][0]]; } } } void build(l x,l tp) { id[x]=++dfscnt;top[x]=tp;a[dfscnt]=w[x]; if (son[x]) build(son[x],tp); for (int i=o[x];i;i=s[i][1]) if ((s[i][0]!=f[x])&&(son[x]!=s[i][0])) build(s[i][0],s[i][0]); } void xia(l r,l z,l y) { l k=z+y>>1;lazy[ll(r)]+=lazy[r];lazy[rr(r)]+=lazy[r]; sgm[ll(r)]+=(k-z+1)*lazy[r]; sgm[rr(r)]+=(y-k)*lazy[r]; sgm[ll(r)]%=p;sgm[ll(r)]%=p;lazy[r]=0; } void js(l r,l z,l y) { if (z==y) {sgm[r]=a[z];if (sgm[r]>p) sgm[r]%=p;return;} l k=z+y>>1;js(ll(r),z,k);js(rr(r),k+1,y);sgm[r]=(sgm[ll(r)]+sgm[rr(r)])%p; } void qjxg(l r,l z,l y,l zz,l yy,l v) { if (z>yy||y<zz) return; if (z>=zz&&y<=yy) { lazy[r]+=v;sgm[r]+=(y-z+1)*v;return;} if (lazy[r]) xia(r,z,y);l k=z+y>>1; if (zz<=k) qjxg(ll(r),z,k,zz,yy,v);if (yy>k) qjxg(rr(r),k+1,y,zz,yy,v); sgm[r]=(sgm[ll(r)]+sgm[rr(r)])%p; } l cx(l r,l z,l y,l zz,l yy) { if (z>yy||y<zz) return 0; if (z>=zz&&y<=yy) return sgm[r]%p; l k=z+y>>1;if (lazy[r]) xia(r,z,y); return (cx(ll(r),z,k,zz,yy)+cx(rr(r),k+1,y,zz,yy))%p; } l qiulu(l x,l y) { l ans=0;while (top[x]!=top[y]) { if (d[top[x]]<d[top[y]]) swap(x,y); ans+=cx(1,1,n,id[top[x]],id[x]);ans%=p;x=f[top[x]]; } if (d[x]>d[y]) swap(x,y);ans+=cx(1,1,n,id[x],id[y]);ans%=p; return ans; } void jialu(l x,l y,l v) { v%=p;while (top[x]!=top[y]) { if (d[top[x]]<d[top[y]]) swap(x,y); qjxg(1,1,n,id[top[x]],id[x],v);x=f[top[x]]; } if (d[x]>d[y]) swap(x,y);qjxg(1,1,n,id[x],id[y],v); } int main() { l x,y,v,flag;cin>>n>>m>>r>>p;for (int i=1;i<=n;i++) scanf("%lld",&w[i]); for (int i=1;i<n;i++) {scanf("%lld%lld",&x,&y);jia(x,y);jia(y,x);}dfs(r,0,1);build(r,r);js(1,1,n); for (int i=1;i<=m;i++) {scanf("%lld",&flag); if (flag==1) {scanf("%lld%lld%lld",&x,&y,&v);jialu(x,y,v);} if (flag==2) {scanf("%lld%lld",&x,&y);printf("%lld ",qiulu(x,y));} if (flag==3) {scanf("%lld%lld",&x,&v);v%=p;qjxg(1,1,n,id[x],id[x]+siz[x]-1,v);} if (flag==4) {scanf("%lld",&x);printf("%lld ",cx(1,1,n,id[x],id[x]+siz[x]-1)%p);} } return 0; }
十四、
最小费用最大流
#include <bits/stdc++.h> using namespace std; const int N=5010,M=100010,inf=2e9; int head,tail,cnt=-1,n,m,s,t,cost=0; int q[N*10],v[N],ss[M*2][4],o[N],d[N],vis[N]; void jia(int a,int b,int c,int cc) { ss[++cnt][0]=b;ss[cnt][1]=o[a]; ss[cnt][2]=c;ss[cnt][3]=cc;o[a]=cnt; ss[++cnt][0]=a;ss[cnt][1]=o[b]; ss[cnt][2]=0;ss[cnt][3]=-cc;o[b]=cnt; } int dfs(int x,int flow) { v[x]=1;int rest=0;if (x==t) return flow; for (int i=o[x];i!=-1;i=ss[i][1]) { if ((d[ss[i][0]]==d[x]-ss[i][3])&&(v[ss[i][0]]==0)&&(ss[i][2]!=0)) { int di=dfs(ss[i][0],min(flow-rest,ss[i][2])); if (di>0) {rest+=di;ss[i][2]-=di;ss[i^1][2]+=di;} } } return rest; } bool spfa() { for (int i=1;i<=n;i++) d[i]=inf,vis[i]=0; head=1;tail=2;q[1]=t;d[t]=0;vis[t]=1; while (head!=tail) { int u=q[head]; for (int i=o[u];i!=-1;i=ss[i][1]) { if ((d[ss[i][0]]>d[u]-ss[i][3])&&(ss[i^1][2]!=0)) { d[ss[i][0]]=d[u]-ss[i][3]; if (!vis[ss[i][0]]) { vis[ss[i][0]]=1;q[tail++]=ss[i][0];if (tail==n+1) tail=1; } } } q[head++]=0;vis[u]=0;if (head==n+1) head=1; } return d[s]!=inf; } void FU_DUI_SUAN_FA_BO_DA_JING_SHEN() { int ans=0,cntt=1; while (spfa()) { v[t]=1; while (v[t]) { memset(v,0,sizeof(v)); int l=dfs(s,inf);ans+=l;cost+=l*d[s]; } } cout<<ans<<" "<<cost<<endl; } int main() { int a,b,c,cc; memset(o,-1,sizeof(o)); cin>>n>>m>>s>>t; for (int i=1;i<=m;i++) { scanf("%d%d%d%d",&a,&b,&c,&cc); jia(a,b,c,cc); } FU_DUI_SUAN_FA_BO_DA_JING_SHEN(); return 0; }
十五、
堆(手打)
#include <bits/stdc++.h> using namespace std; int n,flag,heap[1000010],heapsize; void jiaru(int d) { int now,next;heap[++heapsize]=d;now=heapsize; while (now>1) { next=now>>1;if (heap[now]>=heap[next]) break; swap(heap[now],heap[next]);now=next; } return; } int shanchu_quchu() { int now,next,res;res=heap[1];heap[1]=heap[heapsize--];now=1; while (now*2<=heapsize) { next=now*2; if (next<heapsize&&heap[next+1]<heap[next]) next++; if (heap[now]<=heap[next]) break;swap(heap[now],heap[next]); now=next; } return res; } int main() { cin>>n;int x; while (n--) { scanf("%d",&flag); if (flag==1) {scanf("%d",&x);jiaru(x);} if (flag==2) {printf("%d ",heap[1]);} if (flag==3) {int daiti=shanchu_quchu();} } return 0; }
十六、
优先队列(STL)
#include <bits/stdc++.h> using namespace std; int n,flag,a; priority_queue <int> heap; int main() { cin>>n; for (int i=1;i<=n;i++) { cin>>flag; if (flag==1) { cin>>a; heap.push(-a); } else if (flag==2) { int f=heap.top(); cout<<-f<<endl; } else heap.pop(); } return 0; }
十七、
迪杰斯特拉(堆优化版本)
#include <bits/stdc++.h> #define MAXN 10010 using namespace std; typedef pair<int,int>Pair; struct node { int u,w,v,next; }e[500010]; int dis[MAXN],st[MAXN]; bool flag[MAXN]; int tot,start,n,m,x,y,z; void add(int x,int y,int z) { e[++tot].u=x;e[tot].v=y; e[tot].w=z; e[tot].next=st[x];st[x]=tot; } int dijsktra(int start) { memset(dis,127,sizeof dis); memset(flag,0,sizeof flag); dis[start]=0;priority_queue< Pair,vector<Pair>,greater<Pair> >que; que.push(make_pair(dis[start],start)); while (!que.empty()) { Pair now=que.top();que.pop(); if (flag[now.second]) continue; flag[now.second]=1; for (int i=st[now.second];i;i=e[i].next) if (dis[now.second]+e[i].w<dis[e[i].v]) { dis[e[i].v]=dis[now.second]+e[i].w; if (!flag[e[i].v]) que.push(make_pair(dis[e[i].v],e[i].v)); } } for (int i=1;i<=n;i++) { if (dis[i]==2139062143) dis[i]=2147483647; printf("%d ",dis[i]); } } int main() { scanf("%d%d%d",&n,&m,&start); for (int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); } dijsktra(start); }
十八、
迪杰斯特拉(线段树版本)
#include <bits/stdc++.h> using namespace std; const int maxn =10007; const int maxm = 500007; const int INF = 0x7fffffff; int n,m; inline int read() { int x=0; char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } struct node{ int v,next,w; }edge[maxm]; int num=0,head[maxn]; inline void add_edge(int a,int b,int c) { edge[++num].v=b;edge[num].w=c;edge[num].next=head[a];head[a]=num; } int dis[maxn],ans[maxn],s,t; int tree[maxn<<2],leaf; inline int check(int i,int j) { return dis[i]<dis[j]?i:j; } inline void build() { std::memset(dis,0x3f,sizeof dis); for (leaf=1;leaf<=n;leaf<<=1);--leaf; for (int i=1;i<=n;++i)tree[leaf+i]=i; } inline void modify(int x,int y) { dis[x]=y,x+=leaf,x>>=1; while(x) tree[x]=check(tree[x<<1],tree[x<<1|1]),x=x>>1; } void dijkstra(int s) { build();dis[s]=0;int u=s; for (int i=1;i<=n;++i) { ans[u]=dis[u]; const int disu=dis[u]; modify(u,INF); for (int j=head[u];j;j=edge[j].next){ int v=edge[j].v; if (dis[v]<INF&&dis[v]>disu+edge[j].w) modify(v,disu+edge[j].w); } u=tree[1]; } } inline void put(int x) { if (x>9) put(x/10); putchar(x%10+48); } int main() { int k; n=read(),m=read(),k=read(); for (int a,b,c,i=1;i<=m;++i) { a=read(),b=read(),c=read(); add_edge(a,b,c); } dijkstra(k); for (int i=1;i<=n;++i) { if (dis[i]==0x3f3f3f3f) ans[i]=INF; put(ans[i]);putchar(' '); } putchar(' '); return 0; }
十九、
普通平衡树(splay)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=100010; int ch[N][2],f[N],ky[N],ct[N],siz[N],sz,rt; void clear(int x) { ch[x][0]=ch[x][1]=f[x]=siz[x]=ct[x]=ky[x]=0; return; } bool get(int x) { return ch[f[x]][1]==x; } void update(int x) { if (x) { siz[x]=ct[x]; if (ch[x][0]) siz[x]+=siz[ch[x][0]]; if (ch[x][1]) siz[x]+=siz[ch[x][1]]; } return; } void rotate(int x) { int old=f[x],oldf=f[old],which=get(x); ch[old][which]=ch[x][which^1];f[ch[old][which]]=old; ch[x][which^1]=old;f[old]=x;f[x]=oldf; if (oldf) ch[oldf][ch[oldf][1]==old]=x; update(old);update(x); } void splay(int x) { for (int fa;fa=f[x];rotate(x)) if (f[fa]) rotate((get(x)==get(fa))?fa:x); rt=x;return; } void insert(int v) { if (!rt) { sz++;ch[sz][0]=ch[sz][1]=f[sz]=0; ky[sz]=v;ct[sz]=1;siz[sz]=1;rt=sz; return; } int now=rt,fa=0; while (1) { if (ky[now]==v) { ct[now]++; update(now);update(fa); splay(now);break; } fa=now;now=ch[now][ky[now]<v]; if (!now) { sz++;ch[sz][0]=ch[sz][1]=0;ky[sz]=v;siz[sz]=1; ct[sz]=1;f[sz]=fa;ch[fa][ky[fa]<v]=sz; update(fa);splay(sz);break; } } return; } int find(int v) { int ans=0,now=rt; while (1) { if (v<ky[now]) now=ch[now][0]; else { ans+=(ch[now][0]?siz[ch[now][0]]:0); if (v==ky[now]) {splay(now);return ans+1;} ans+=ct[now];now=ch[now][1]; } } return 0; } int findx(int x) { int now=rt; while (1) { if (ch[now][0]&&x<=siz[ch[now][0]]) now=ch[now][0]; else { int tt=(ch[now][0]?siz[ch[now][0]]:0)+ct[now]; if (x<=tt) return ky[now]; x-=tt;now=ch[now][1]; } } return 0; } int pre() { int now=ch[rt][0]; while (ch[now][1]) now=ch[now][1]; return now; } int next() { int now=ch[rt][1]; while (ch[now][0]) now=ch[now][0]; return now; } void del(int x) { int whatever=find(x); if (ct[rt]>1) {ct[rt]--;update(rt);return;} if (!ch[rt][0]&&!ch[rt][1]) {clear(rt);rt=0;return;} if (!ch[rt][0]) { int oldrt=rt;rt=ch[rt][1];f[rt]=0;clear(oldrt);return; } else if (!ch[rt][1]) { int oldrt=rt;rt=ch[rt][0];f[rt]=0;clear(oldrt);return; } int leftbig=pre(),oldrt=rt; splay(leftbig); ch[rt][1]=ch[oldrt][1];f[ch[oldrt][1]]=rt; clear(oldrt);update(rt);return; } int main() { int n,a,b;cin>>n;int rrr=0; while (n--) { scanf("%d%d",&a,&b); if (a==1) insert(b)/*,cout<<++rrr<<"i"<<endl*/; else if (a==2) del(b)/*,cout<<++rrr<<"d"<<endl*/; else if (a==3) printf("%d ",find(b))/*,cout<<++rrr<<"f"<<endl*/; else if (a==4) printf("%d ",findx(b))/*,cout<<++rrr<<"x"<<endl*/; else if (a==5) {insert(b);printf("%d ",ky[pre()]);del(b)/*,cout<<++rrr<<"p"<<endl*/;} else {insert(b);printf("%d ",ky[next()]);del(b)/*,cout<<++rrr<<"n"<<endl*/;} } return 0; }
二十、
矩阵快速幂
#include <bits/stdc++.h> using namespace std; long long n,p; long long mod=1e9+7; long long ans[105][105]; long long a[105][105],b[105][105]; void lu() { memcpy(b,ans,sizeof(ans)); memset(ans,0,sizeof(ans)); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) ans[i][j]=(ans[i][j]+(b[i][k]*a[k][j])%mod)%mod; } void ge() { memcpy(b,a,sizeof(a)); memset(a,0,sizeof(a)); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) a[i][j]=(a[i][j]+(b[i][k]*b[k][j])%mod)%mod; } int main() { cin>>n>>p;p--; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) cin>>ans[i][j]; memcpy(a,ans,sizeof(a)); while (p) { if (p&1) lu(); ge();p>>=1; } for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) cout<<ans[i][j]<<' '; cout<<endl; } return 0; }
二十一、
普通平衡树(treap)
#include <bits/stdc++.h> using namespace std; const int N=11e4,big=2e9; int top,sz,ch[N][2],siz[N],rk[N],num[N],f[N],small=-big; void update(int x) { siz[x]=siz[ch[x][1]]+siz[ch[x][0]]+1; return; } int rotate(int j,int get) { int nson=ch[j][get],other=(get^1); ch[j][get]=ch[nson][other]; ch[nson][other]=j; update(j);update(nson); return nson; } int insert(int j,int v) { if (!j) { sz++;siz[sz]=1; num[sz]=v;rk[sz]=rand(); return sz; } bool get=(num[j]<=v); siz[j]++;ch[j][get]=insert(ch[j][get],v); if (rk[j]>rk[ch[j][get]]) return rotate(j,get); return j; } int del(int j,int v) { if (num[j]==v) { if (ch[j][0]&&ch[j][1]) { int son=ch[j][0],fa=0; while (ch[son][1]) fa=son,son=ch[son][1],siz[fa]--; if (son==ch[j][0]) { ch[son][1]=ch[j][1];rk[son]=rk[j]; siz[son]=siz[j]-1;return son; } ch[fa][1]=ch[son][0];ch[son][0]=ch[j][0]; ch[son][1]=ch[j][1];rk[son]=rk[j];siz[son]=siz[j]-1; return son; } if (ch[j][0]) return ch[j][0]; return ch[j][1]; } int get=(num[j]<v); ch[j][get]=del(ch[j][get],v);siz[j]--;return j; } int newww(int j,int x) { if (!j) return -1; if (num[j]==x) { int ans=newww(ch[j][0],x); return ans==-1?j:ans; } if (num[j]>x) return newww(ch[j][0],x); return newww(ch[j][1],x); } int find(int i,int j,int x) { if (i==j) return siz[ch[i][0]]+1; if (num[i]>=x) return find(ch[i][0],j,x); return find(ch[i][1],j,x)+siz[ch[i][0]]+1; } int findx(int j,int x) { if (siz[ch[j][0]]==x-1) return num[j]; if (siz[ch[j][0]]>=x) return findx(ch[j][0],x); return findx(ch[j][1],x-siz[ch[j][0]]-1); } int pre(int j,int x) { if (!j) return small; if (num[j]<x) return max(num[j],pre(ch[j][1],x)); return pre(ch[j][0],x); } int next(int j,int x) { if (!j) return big; if (num[j]>x) return min(num[j],next(ch[j][0],x)); return next(ch[j][1],x); } int main() { srand(time(NULL)); int n,m,x;cin>>n; while (n--) { scanf("%d%d",&m,&x); if (m==1) top=insert(top,x); if (m==2) top=del(top,x); if (m==3) printf("%d ",find(top,newww(top,x),x)); if (m==4) printf("%d ",findx(top,x)); if (m==5) printf("%d ",pre(top,x)); if (m==6) printf("%d ",next(top,x)); } return 0; }
二十二、
线性筛素数(欧拉筛)
#include <bits/stdc++.h> using namespace std; int n,m; int prime[10000010]; bool isprime[10000010]; int primesize; int gi() { char c=getchar();int a=0;bool f=0; while (c>'9'||c<'0') {if (c=='-') f=1;c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0';c=getchar();} return f?-a:a; } void shai(int listsize) { memset(isprime,true,sizeof(isprime)); isprime[1]=false; for (int i=2;i<=listsize;i++) { if (isprime[i]) prime[++primesize]=i; for (int j=1;j<=primesize&&i*prime[j]<=listsize;j++) { isprime[i*prime[j]]=false; if (i%prime[j]==0) break; } } } int main() { n=gi();m=gi(); shai(n); for (int i=1;i<=m;i++) { int p=gi(); if (isprime[p]==true) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }
二十三、
KMP算法 字符串匹配
#include <bits/stdc++.h> using namespace std; int kmp[1000010]; char a[1000010],b[1000010]; int main() { scanf("%s%s",a,b); int la=strlen(a),lb=strlen(b),k=0; for (int i=1;i<lb;i++) { while (k&&b[i]!=b[k]) k=kmp[k]; kmp[i+1]=(b[i]==b[k])?++k:0; } k=0; for (int i=0;i<la;i++) { while (k&&a[i]!=b[k]) k=kmp[k]; k+=(a[i]==b[k])?1:0; if (k==lb) printf("%d ",i-lb+2); } for (int i=1;i<=lb;i++) printf("%d ",kmp[i]); return 0; }
二十四、
tarjan缩点+最短路
#include <bits/stdc++.h> using namespace std; int last[100100],len=0,sccno[10010]={0},scc=0,n,m,u,v,w[10010]={0}; int dfn[10010]={0},low[10010]={0},dfscnt=0,wscc[10010]={0}; int f[100010]={0},t[100010]={0},ans=-2147483648,dis[10010]={0}; bool vis[10010]; stack <int> s; struct edge { int next,to; }e[100100]; int gi() { char c=getchar();bool f=0;int a=0; while (c<'0'||c>'9') {if (c=='-') f=1;c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0';c=getchar();} return f?-a:a; } void add(int x,int y) { e[++len].to=y; e[len].next=last[x]; last[x]=len; } void init() { memset(last,-1,sizeof(last)); n=gi();m=gi(); for (int i=1;i<=n;i++) w[i]=gi(); for (int i=1;i<=m;i++) { u=gi();v=gi();add(u,v);f[i]=u;t[i]=v; } } int tarjan(int r) { s.push(r); dfn[r]=low[r]=++dfscnt; for (int i=last[r];i!=-1;i=e[i].next) { int y=e[i].to; if (!dfn[y]) {tarjan(y);low[r]=min(low[r],low[y]);} else if (!sccno[y]) low[r]=min(low[r],dfn[y]); } if (dfn[r]==low[r]) { scc++; while (1) { int x=s.top();sccno[x]=scc;wscc[scc]+=w[x]; s.pop();if (x==r) break; } } } void build() { len=0; memset(last,-1,sizeof(last)); for (int i=1;i<=m;i++) { if (sccno[f[i]]!=sccno[t[i]]) add(sccno[f[i]],sccno[t[i]]); } } int bfs(int x) { memset(dis,-1,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[x]=wscc[x]; queue <int> q; vis[x]=true;q.push(x); while (!q.empty()) { int u=q.front();q.pop();vis[u]=false; for (int i=last[u];i!=-1;i=e[i].next) { int v=e[i].to; if (dis[v]<dis[u]+wscc[v]) { dis[v]=dis[u]+wscc[v]; if (!vis[v]) {vis[v]=true;q.push(v);} } } } for (int i=1;i<=scc;i++) ans=max(dis[i],ans); } int main() { init(); for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i); build(); for (int i=1;i<=scc;i++) bfs(i); printf("%d ",ans); return 0; }
二十五、
主席树
#include <bits/stdc++.h> using namespace std; const int N=300010; struct value {int x,id;} a[N]; struct node {int l,r,sum;} ch[N*20]; int rank[N],root[N],cnt,n,m; bool cmp(value x,value y) {return x.x<y.x;} void init() { cnt=1; root[0]=0; ch[0].l=ch[0].r=ch[0].sum; } void update(int num,int &rt,int l,int r) { ch[cnt++]=ch[rt]; rt=cnt-1; ++ch[rt].sum; if (l==r) return; int mid=l+r>>1; if (num<=mid) update(num,ch[rt].l,l,mid); else update(num,ch[rt].r,mid+1,r); } int query(int i,int j,int k,int l,int r) { int d=ch[ch[j].l].sum-ch[ch[i].l].sum; if (l==r) return l; int mid=l+r>>1; if (k<=d) return query(ch[i].l,ch[j].l,k,l,mid); else return query(ch[i].r,ch[j].r,k-d,mid+1,r); } int main() { cin>>n>>m; for (int i=1;i<=n;++i) { scanf("%d",&a[i].x); a[i].id=i; } sort(&a[1],&a[n+1],cmp); for (int i=1;i<=n;++i) rank[a[i].id]=i; init(); for (int i=1;i<=n;++i) { root[i]=root[i-1]; update(rank[i],root[i],1,n); } int l,r,k; for (int i=1;i<=m;++i) { scanf("%d%d%d",&l,&r,&k); printf("%d ",a[query(root[l-1],root[r],k,1,n)].x); } }
二十六、
字典树(trie树)
#include <bits/stdc++.h> using namespace std; char s[100]; const int N=2000010; int tot=1,tree[N][26],n; void insert(char *s,int rt) { for (int i=0;s[i];i++) { int x=s[i]-'a'; if (!tree[rt][x]) tree[rt][x]=++tot; rt=tree[rt][x]; } } bool find(char *s,int rt) { for (int i=0;s[i];i++) { int x=s[i]-'a'; if (!tree[rt][x]) return 0; rt=tree[rt][x]; } return 1; } int main() { tot=0;int rt=1; scanf("%d",&n); for (int i=1;i<=n;i++) {scanf("%s",s);insert(s,rt);} scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%s",s); if (find(s,rt)) printf("YES "); else printf("NO "); } return 0; }
二十七、
快速排序
#include <bits/stdc++.h> using namespace std; int n,a[100010]={0}; inline void qsort(int l,int r) { if(l==r) return; int i=l,j=r,mid=a[(l+r)>>1]; do { while (a[i]<mid) i++; while (a[j]>mid) j--; if (i<=j) { swap(a[i],a[j]); i++;j--; } } while(i<=j); if (l<j) qsort(l,j); if (i<r) qsort(i,r); } int main() { while (scanf("%d",&n)!=EOF) { for (int i=1;i<=n;i++) { scanf("%d",&a[i]); } qsort(1,n); for (int i=1;i<=n;i++) printf("%d ",a[i]); printf(" "); } return 0; }
二十八、
FFT快速傅里叶(假的 其实是python)
print(int(input())*int(input())) if input() else 0
二十九、
并查集
#include <bits/stdc++.h> using namespace std; #define INF 10000+5 #define INF2 200000+5 int n,m; struct Node{ int rank; int father; }node[INF+1]; int get_bigfather(int k) { if(node[k].father==k) return k; else { node[k].father=get_bigfather(node[k].father); return node[k].father; } } void merge(int u,int v) { u=get_bigfather(u); v=get_bigfather(v); if(node[u].rank>node[v].rank) node[v].father=u; else { node[u].father=v; if(node[u].rank==node[v].rank) node[v].rank++; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) node[i].father=i; for(int i=1;i<=m;i++) { int temp,u,v; scanf("%d%d%d",&temp,&u,&v); if(temp==1) merge(u,v); else { if(get_bigfather(u)==get_bigfather(v)) printf("Y "); else printf("N "); } } return 0; }
三十、
dfs版spfa判断负环
#include <bits/stdc++.h> using namespace std; int n,m,cnt,flag; int head[10010]; bool vis[10010]; double dis[10010]; struct node{ int to,next;double v; }edge[10010]; int read() { int x=0,w=1;char ch=getchar(); while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*w; } void add(int x,int y,double v) { cnt++; edge[cnt].to=y; edge[cnt].next=head[x]; edge[cnt].v=v; head[x]=cnt; } void spfa(int k,double jian) { vis[k]=1; int v; for(int i=head[k];i;i=edge[i].next) { v=edge[i].to; if(dis[v]>dis[k]+edge[i].v-jian) { if(vis[v]) { flag=1; return; } dis[v]=dis[k]+edge[i].v-jian; spfa(v,jian); if(flag) return; } } vis[k]=0; } bool check(double mid) { flag=0; memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { spfa(i,mid); if(flag) return 1; } return 0; } int main() { int x,y; double z; n=read();m=read(); for(int i=1;i<=m;i++) { x=read();y=read(); scanf("%lf",&z); add(x,y,z); } double l=-10000000,r=10000000,mid; while(r-l>1e-10) { mid=(l+r)/2; if(check(mid)) { r=mid; } else { l=mid; } } printf("%.8lf",mid); return 0; }
三十一、
BF算法(暴风算法)
#include <bits/stdc++.h> using namespace std; int index_bf(char *s,char *t,int pos); int index_bf_self(char *s,char *t,int index); int main() { char s[]="6he3wor"; char t[]="3wor"; int m=index_bf(s,t,2); printf("index_bf:%d ",m); m=index_bf_self(s,t,2); printf("index_bf_self:%d ",m); exit(0); } int index_bf(char *s,char *t,int pos) { int i,j; if(pos>=1 && pos <=s[0]-'0') { i=pos; j=1; while(i<=s[0]-'0'&&j<=t[0]-'0') { if(s[i]==t[j]) { i++; j++; } else { j=1; i=i-j+2; } if(j>t[0]-'0') { return i-t[0]+'0'; } } return -1; } else { return -1; } } int index_bf_self(char *s,char *t,int index) { int i=index,j=0; while(s[i]!='