从2017年暑假到现在手打的模板↑_↑
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('\n'); } 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\n",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\n",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\n",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\n",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\n",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('\n'); 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\n",find(b))/*,cout<<++rrr<<"f"<<endl*/; else if (a==4) printf("%d\n",findx(b))/*,cout<<++rrr<<"x"<<endl*/; else if (a==5) {insert(b);printf("%d\n",ky[pre()]);del(b)/*,cout<<++rrr<<"p"<<endl*/;} else {insert(b);printf("%d\n",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\n",find(top,newww(top,x),x)); if (m==4) printf("%d\n",findx(top,x)); if (m==5) printf("%d\n",pre(top,x)); if (m==6) printf("%d\n",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\n",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\n",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\n",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\n"); else printf("NO\n"); } 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("\n"); } 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\n"); else printf("N\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\n",m); m=index_bf_self(s,t,2); printf("index_bf_self:%d\n",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]!='\0') { while(*(t+j)!='\0' && *(s+i+j)!='\0') { if(*(t+j)!=*(s+i+j)) break; j++; } if(*(t+j)=='\0') { return i; } i++; j=0; } return -1; }
三十二、
高斯消元法Gauss
//Guss #include <bits/stdc++.h> using namespace std; int n; double f[105][105]; const double eps=1e-8; int main() { scanf("%d",&n); for (int i=0;i<n;i++)//读入系数和值 for (int j=0;j<=n;j++) scanf("%lf",&f[i][j]); for (int i=0;i<n;i++) { int ch=i; for (int j=i;j<n;j++)//选择绝对值最大的减少误差 if (fabs(f[j][i]-f[ch][i])<=eps) ch=j; for (int j=0;j<=n;j++) swap(f[i][j],f[ch][j]);//交换 if (fabs(f[i][i])<=eps) {//无解情况 printf("No Solution\n"); return 0;//如果当前位置为零 则无解 0x=A } for (int j=i+1;j<=n;j++) f[i][j]/=f[i][i];//系数化1 //自己那位不必要除 无影响 for (int j=0;j<n;j++) if (i!=j) for (int k=i+1;k<=n;k++) f[j][k]-=f[j][i]*f[i][k]; //加减法去掉系数值 } for (int i=0;i<n;i++) printf("%.2lf\n",f[i][n]);//输出 return 0; }
三十三、
扫描线(洛谷 ‘楼房’)
#include <bits/stdc++.h> #define N 100010 using namespace std; int n,cnt,num; multiset <int> s; struct thing {int h,l,r;}a[N]; struct lines {int up,x,k;}l[N*2]; struct anspr {int ax,ay;}ans[N*4]; bool cmp(lines i,lines j) { if (i.x!=j.x) return i.x<j.x; if (i.k!=j.k) return i.k<j.k; if (i.k==1) return i.up>j.up; if (i.k==2) return i.up<j.up; } int main() { cin>>n; for (int i=1;i<=n;i++) { int q,w,e; scanf("%d%d%d",&q,&w,&e); a[i].h=q,a[i].l=w,a[i].r=e; l[++cnt].up=q;l[cnt].x=w,l[cnt].k=1; l[++cnt].up=q;l[cnt].x=e,l[cnt].k=2; } sort(l+1,l+1+cnt,cmp); s.insert(0); for (int i=1;i<=cnt;i++) { int mx=*s.rbegin(); if (l[i].k==1) { if (l[i].up<=mx) s.insert(l[i].up); else { ans[++num].ax=l[i].x;ans[num].ay=mx; ans[++num].ax=l[i].x;ans[num].ay=l[i].up; s.insert(l[i].up); } } if (l[i].k==2) { if (l[i].up==mx&&s.count(mx)==1) { s.erase(mx); ans[++num].ax=l[i].x;ans[num].ay=l[i].up; ans[++num].ax=l[i].x;ans[num].ay=*s.rbegin(); } else s.erase(s.find(l[i].up)); } } cout<<num<<endl; for (int i=1;i<=num;i++) printf("%d %d\n",ans[i].ax,ans[i].ay); return 0; }
三十四、
Meeting-in-the-Middle
#include <bits/stdc++.h> using namespace std; const int maxn=24; map <int,int> table; int bitcount(int x) { return x==0?0:bitcount(x/2)+(x&1); }//这个函数用来计算这个数在二进制下有多少个1 int main() { int n,A[maxn]; char s[1000]; while (scanf("%d",&n)==1&&n) {//读入多组数据 for (int i=0;i<n;i++) { scanf("%s",s);//输入字符串 A[i]=0; for (int j=0;s[j]!='\0';j++) A[i]^=(1<<(s[j]-'A'));//计算每一串的<=26位二进制值 } table.clear();//清空table映射 int n1=n/2,n2=n-n1;//将待测数据分成两部分 //接下来循环计算2^(n/2)个属于前半部分的子集 for (int i=0;i<(1<<n1);i++) { int x=0; for (int j=0;j<n1;j++) if (i&(1<<j)) x^=A[j]; if (!table.count(x)||bitcount(table[x])<bitcount(i)) table[x]=i; }//取每个计算结果中的最大值 //最后处理后半部分 int ans=0; for (int i=0;i<(1<<n2);i++) { int x=0; for (int j=0;j<n2;j++) if (i&(1<<j)) x^=A[n1+j]; if (table.count(x)&&bitcount(ans)<bitcount(table[x])+bitcount(i)) ans=(i<<n1)^table[x]; }//每次计算前查找映射中是否出现过 printf("%d\n",bitcount(ans)); for (int i=0;i<n;i++) if (ans&(1<<i)) printf("%d ",i+1); printf("\n");//输出部分 } return 0; }
三十五、
左偏树(可并堆)
#include <bits/stdc++.h> using namespace std; const int N=101000; struct leftist{ int l,r,k,f,d; }h[N]; int n,m; int merge(int u,int v) { if (!u||!v) return u+v; if (h[u].k>h[v].k||(h[u].k==h[v].k&&u>v)) swap(u,v); int &ul=h[u].l,&ur=h[u].r; ur=merge(ur,v); h[ur].f=u; if (h[ul].d<h[ur].d) swap(ul,ur); h[u].d=h[ur].d+1; return u; } void erase(int u) { int ul=h[u].l,ur=h[u].r; h[u].k=-1; h[ul].f=0; h[ur].f=0; merge(ul,ur); } int find(int x) { return h[x].f?find(h[x].f):x; } int main() { cin>>n>>m; h[0].d=-1; for (int i=1;i<=n;i++) scanf("%d",&h[i].k); for (int i=1;i<=m;i++) { int opt,x,y; scanf("%d%d",&opt,&x); if (opt==1) { scanf("%d",&y); if (h[x].k!=-1 && h[y].k!=-1) { int p=find(x),q=find(y); if (p!=q) merge(p,q); } } else if (opt==2) { if (h[x].k==-1) printf("-1\n"); else { int p=find(x); printf("%d\n",h[p].k); erase(p); } } } return 0; }
三十六、
分块(小b的询问)
// luogu-judger-enable-o2 #include <bits/stdc++.h> using namespace std; const int N=50010,S=250; int n,m,q,a[N],s[S][S]; int f[S][N],block,num; int belong[N],l[S],r[S],tmp[N]; void build() { block=sqrt(n); num=n/block; if (n%block) num++; for (int i=1;i<=num;i++) l[i]=(i-1)*block+1,r[i]=i*block; r[num]=n; for (int i=1;i<=n;i++) belong[i]=(i-1)/block+1; for (int i=1;i<=num;i++) { for (int j=1;j<=n;j++) f[i][a[j]]=f[i-1][a[j]]; for (int j=l[i];j<=r[i];j++) f[i][a[j]]++; } for (int i=1;i<=num;i++) for (int j=i;j<=num;j++) { s[i][j]=s[i][j-1]; for (int k=l[j];k<=r[j];k++) { int p=f[j-1][a[k]]-f[i-1][a[k]]; s[i][j]+=2*(p+tmp[a[k]])+1; tmp[a[k]]++; } for (int k=l[j];k<=r[j];k++) tmp[a[k]]=0; } } long long ask(int ls,int rs) { long long ans=0; if (belong[ls]==belong[rs]) { for (int i=ls;i<=rs;i++) { ans+=2*tmp[a[i]]+1; tmp[a[i]]++; } for (int i=ls;i<=rs;i++) tmp[a[i]]=0; return ans; } for (int i=ls;i<=r[belong[ls]];i++) { int p=f[belong[rs]-1][a[i]]-f[belong[ls]][a[i]]; ans+=2*(p+tmp[a[i]])+1; tmp[a[i]]++; } for (int i=l[belong[rs]];i<=rs;i++) { int p=f[belong[rs]-1][a[i]]-f[belong[ls]][a[i]]; ans+=2*(p+tmp[a[i]])+1; tmp[a[i]]++; } for (int i=ls;i<=r[belong[ls]];i++) tmp[a[i]]=0; for (int i=l[belong[rs]];i<=rs;i++) tmp[a[i]]=0; if (belong[ls]+1==belong[rs]) return ans; return ans+s[belong[ls]+1][belong[rs]-1]; } int main() { ios::sync_with_stdio(0); cin>>n>>m>>q; for (int i=1;i<=n;i++) cin>>a[i]; build(); while (m--) { int ls,rs; cin>>ls>>rs; cout<<ask(ls,rs)<<endl; } return 0; }
三十七、
莫队(小z的袜子)
#include <bits/stdc++.h> using namespace std; int id[50005]; const int N=50005; struct Mo { int x,y,num; bool operator < (const Mo &a) const { if (id[x]==id[a.x]) return (id[x]&1)?y<a.y:y>a.y; return x<a.x; } }q[N]; int n,m,c[N],len,l=1,r; unsigned int cnt[N],ans[N][2],g,k,now; long long gcd(long long a,long long b) { while (b^=a^=b^=a%=b);return a; } int main() { ios::sync_with_stdio(false); cin>>n>>m; for (int i=1;i<=n;i++) cin>>c[i]; len=sqrt(n); for (int i=1;i<=m;i++) cin>>q[i].x>>q[i].y,q[i].num=i,id[i]=i/len+1; sort(q+1,q+1+m); for (int i=1;i<=m;i++) { if (q[i].x==q[i].y) continue; while (l<q[i].x) { --cnt[c[l]];now-=cnt[c[l]];++l; } while (l>q[i].x) { --l;now+=cnt[c[l]];++cnt[c[l]]; } while (r<q[i].y) { ++r;now+=cnt[c[r]];++cnt[c[r]]; } while (r>q[i].y) { --cnt[c[r]];now-=cnt[c[r]];--r; } if (!now) continue; k=(unsigned int)(r-l+1)*(r-l); g=gcd(now<<1,k); ans[q[i].num][0]=(now<<1)/g; ans[q[i].num][1]=k/g; } for (int i=1;i<=m;i++) if (!ans[i][0]) cout<<"0/1"<<endl; else cout<<ans[i][0]<<"/"<<ans[i][1]<<endl; return 0; }
三十八、
tarjan求割点
#include <bits/stdc++.h> using namespace std; const int N=100010; bool cut[N]; int dfn[N],low[N],dfscnt; int n,m,s[N*2][2],o[N],cnt,fa[N],size[N]; void add(int x,int y) { s[++cnt][0]=y;s[cnt][1]=o[x];o[x]=cnt; } void tarjan(int x,int fa) { int i=o[x];dfn[x]=low[x]=++dfscnt; while (i!=-1) { if (!dfn[s[i][0]]) { size[x]++;tarjan(s[i][0],x); if (low[s[i][0]]>=dfn[x]) cut[x]=1; else low[x]=min(low[x],low[s[i][0]]); } else if (s[i][0]!=fa) low[x]=min(low[x],dfn[s[i][0]]); i=s[i][1]; } if (size[x]==1&&!fa) cut[x]=0; } int main() { int ans=0; ios::sync_with_stdio(false); cin>>n>>m;int x,y; memset(o,-1,sizeof(o)); for (int i=1;i<=m;i++) { cin>>x>>y;add(x,y);add(y,x); } for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,0); for (int i=1;i<=n;i++) if (cut[i]) ans++; cout<<ans<<endl; for (int i=1;i<=n;i++) if (cut[i]) cout<<i<<' ';cout<<endl; return 0; }
三十九、
凸包(扫描法)
#include <bits/stdc++.h> using namespace std; const int N=10010; struct node { double x,y; }p[N],s[N]; int top,n; bool cmp(node a,node b) { double A=atan2(a.y-p[1].y,a.x-p[1].x); double B=atan2(b.y-p[1].y,b.x-p[1].x); return A==B?a.x<b.x:A<B; } double cross(node a,node b,node c) { return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); } double dis(node a,node b) { return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y)); } int main() { cin>>n; for (int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y); p[0].x=p[0].y=999999999; int k; for (int i=1;i<=n;++i) if (p[0].y>p[i].y||(p[0].y==p[i].y&&p[0].x>p[i].x)) p[0]=p[i],k=i; swap(p[k],p[1]);sort(&p[2],&p[n+1],cmp); s[0]=p[1],s[1]=p[2],top=1; for (int i=3;i<=n;) { if (top&&cross(s[top-1],p[i],s[top])>=0) --top; else s[++top]=p[i++]; } double ans=0; if (top==0) ans=0; else if (top==1) ans=dis(s[0],s[1]); else { s[++top]=s[0]; for (int i=0;i<top;++i) ans+=dis(s[i],s[i+1]); } printf("%.2lf\n",ans); return 0; }
四十、
2-sat(tarjan)
#include <bits/stdc++.h> using namespace std; const int N=2000010; bool flag=1; int n,m,scc,dfscnt; int s[N<<1][2],o[N]; int low[N],dfn[N],sccno[N]; stack <int> sta; void read(int &aa) { aa=0;char c=getchar(); while (c>'9'||c<'0') c=getchar(); while (c>='0'&&c<='9') aa=(aa<<3)+(aa<<1)+(c^48),c=getchar(); } void add(int x,int y) { s[++o[0]][0]=y,s[o[0]][1]=o[x],o[x]=o[0]; } void tarjan(int x) { low[x]=dfn[x]=++dfscnt; sta.push(x); for (int i=o[x];i;i=s[i][1]) { int y=s[i][0]; if (!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); else if (!sccno[y]) low[x]=min(low[x],dfn[y]); } if (dfn[x]==low[x]) { ++scc; while (1) { int y=sta.top(); sta.pop(); sccno[y]=scc; if (x==y) break; } } } int main() { read(n),read(m); int a,b,aval,bval,nota,notb; for (int i=1;i<=m;++i) { read(a),read(aval),read(b),read(bval); nota=aval^1,notb=bval^1; add(a+nota*n,b+bval*n); add(b+notb*n,a+aval*n); } for (int i=1;i<=(n<<1);++i) if (!dfn[i]) tarjan(i); for (int i=1;i<=m;++i) if (sccno[i]==sccno[i+n]) {flag=0;break;} if (flag) { puts("POSSIBLE"); for (int i=1;i<=n;++i) printf("%d ",sccno[i]>sccno[i+n]); } else puts("IMPOSSIBLE"); return 0; }
未完待续。。。