基本算法

  • 快速幂
  1. ll ksm(ll a,ll b)
  2. {
  3. ll ans=;
  4. while(b)
  5. {
  6. if(b&) ans=ans*a%p;
  7. b>>=;
  8. a=a*a%p;
  9. }
  10. return ans;
  11. }

ksm

  • 64位大整数乘法
  1. ll mul(ll a,ll b)
  2. {
  3. ll ans=;
  4. while(b)
  5. {
  6. if(b&) ans=(ans+a)%p;
  7. b>>=;
  8. a=a*%p;
  9. }
  10. return ans;
  11. }

mul

  • 离散化
  1. for(int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
  2. sort(b+,b++n);
  3. int cnt=unique(b+,b++n)-(b+);
  4. for(int i=;i<=n;i++) a[i]=lower_bound(b+,b+cnt+,a[i])-b;

discrete

  • 归并排序求逆序对
  1. void mergesort(int l,int r)
  2. {
  3. if(l==r) return ;
  4. int mid=(l+r)>>;
  5. mergesort(l,mid);
  6. mergesort(mid+,r);
  7. int i=l,j=mid+,k=l-;
  8. while(i<=mid&&j<=r)
  9. {
  10. if(a[i]<=a[j]) b[++k]=a[i],i++;
  11. else b[++k]=a[j],j++,(ans+=mid-i+)%=moder;
  12. }
  13. while(i<=mid) b[++k]=a[i],i++;
  14. while(j<=r) b[++k]=a[j],j++;
  15. for(int qwq=l;qwq<=r;qwq++) a[qwq]=b[qwq];
  16. }

mergesort

  • 全排列
  1. void dfs(int x)
  2. {
  3. for(int i=;i<=n;i++)
  4. if(!vis[i])
  5. {
  6. seq[x]=i;
  7. vis[i]=;
  8. if(x==n) work();
  9. else dfs(x+);
  10. vis[i]=;
  11. }
  12. }

Permutation

  • ST表
  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4.  
  5. using namespace std;
  6.  
  7. int n,m;
  8. int st[][];
  9.  
  10. int sta(int l,int r)
  11. {
  12. int k=log2(r-l+);
  13. return max(st[l][k],st[r-(<<k)+][k]);
  14. }
  15.  
  16. int main()
  17. {
  18. scanf("%d%d",&n,&m);
  19. for(int i=;i<=n;i++) scanf("%d",&st[i][]);
  20. for(int j=;j<=;j++)
  21. for(int i=;i+(<<j)-<=n;i++)
  22. st[i][j]=max(st[i][j-],st[i+(<<(j-))][j-]);
  23. for(int i=;i<=m;i++)
  24. {
  25. int l=,r=;
  26. scanf("%d%d",&l,&r);
  27. printf("%d\n",sta(l,r));
  28. }
  29. return ;
  30. }

ST Table

  • 两种二分
  1. while(l<r)
  2. {
  3. int mid=(l+r)>>;
  4. if(check(mid)) r=mid;
  5. else l=mid+;
  6. }
  7. while(l<r)
  8. {
  9. int mid=(l+r+)>>;
  10. if(check(mid)) r=mid-;
  11. else l=mid;
  12. }

整数域二分

  1. double eps=1e-;
  2. while(l+eps<r)
  3. {
  4. double mid=(l+r)/;
  5. if(check(mid)) r=mid;
  6. else l=mid;
  7. }

实数域二分

  1. void Recantor(ll x)
  2. {
  3. memset(vis,,sizeof(vis));
  4. x--;
  5. int j=;
  6. for(int i=;i<=n;i++)
  7. {
  8. ll t=x/fac[n-i];
  9. for(j=;j<=n;j++)
  10. if(!vis[j])
  11. {
  12. if(!t) break;
  13. t--;
  14. }
  15. printf("%d ",j);
  16. vis[j]=;
  17. x%=fac[n-i];
  18. }
  19. printf("\n");
  20. }
  21.  
  22. ll cantor()
  23. {
  24. ll ans=;
  25. for(int i=;i<=n;i++)
  26. {
  27. int tot=;
  28. for(int j=i+;j<=n;j++)
  29. if(a[j]<a[i]) tot++;
  30. ans+=1ll*tot*fac[n-i];
  31. }
  32. return ans;
  33. }

Cantor&Recantor

其他算法

  • 莫队算法(不带修)
  1. bool cmp(query a,query b)
  2. {
  3. return (a.l/block)^(b.l/block) ? a.l<b.l : (((a.l/block)&) ? a.r<b.r : a.r>b.r);
  4. }//奇偶块排序
  5.  
  6. block=sqrt(n);
  7. for(int i=;i<=n;i++) scanf("%d",&seq[i]);
  8. for(int i=;i<=m;i++)
  9. {
  10. scanf("%d%d",&ask[i].l,&ask[i].r);
  11. ask[i].id=i;
  12. ask[i].in=ask[i].l/block;
  13. }
  14. sort(ask+,ask++m,cmp);
  15. for(int i=;i<=m;i++)
  16. {
  17. int l=ask[i].l,r=ask[i].r;
  18. while(posl<l) remove(posl++);
  19. while(posr>r) remove(posr--);
  20. while(posl>l) add(--posl);
  21. while(posr<r) add(++posr);
  22. ans[ask[i].id]=noww;
  23. }
  24. for(int i=;i<=m;i++) printf("%d\n",ans[i]);

Mo's Algorithm

数学

  • 预处理阶乘和处理逆元求组合数
  1. ll exgcd(ll a,ll b,ll &x,ll &y)
  2. {
  3. if(b==)
  4. {
  5. x=;
  6. y=;
  7. return a;
  8. }
  9. int gu=exgcd(b,a%b,x,y);
  10. int t=x;
  11. x=y;
  12. y=t-a/b*y;
  13. return gu;
  14.  
  15. }
  16.  
  17. ll niyuan(ll hu)
  18. {
  19. x=,y=;
  20. ll tmp=exgcd(hu,p,x,y);
  21. return (x+p)%p;
  22. }
  23.  
  24. ll C(ll k,ll m)
  25. {
  26. ll up=fac[k]%p;
  27. ll down=fac[m]%p*fac[k-m]%p;
  28. ll ans=up*niyuan(down)%p;
  29. return ans;
  30. }
  31.  
  32. void pre()
  33. {
  34. fac[]=;
  35. for(int i=;i<=n+;i++)
  36. fac[i]=(ll)fac[i-]*i%p;
  37. }

Combination

  • 杨辉三角求组合数

  1. C[][]=;C[][]=;
  2. for(int i=;i<=n;i++) C[i][]=,C[i][i]=;
  3. for(int i=;i<=n;i++)
  4. for(int j=;j<=i;j++)
  5. (C[i][j]=C[i-][j]+C[i-][j-])%=moder;

Yang's triangle

数据结构

  • $vector$实现普通平衡树 慎用!!!
  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<vector>
  4.  
  5. using namespace std;
  6.  
  7. int n;
  8. vector<int>v;
  9.  
  10. int main()
  11. {
  12. scanf("%d",&n);
  13. for(int i=;i<=n;i++)
  14. {
  15. int op=,x=;
  16. scanf("%d%d",&op,&x);
  17. if(op==) v.insert(upper_bound(v.begin(),v.end(),x),x);
  18. else if(op==) v.erase(lower_bound(v.begin(),v.end(),x));
  19. else if(op==) printf("%d\n",lower_bound(v.begin(),v.end(),x)-v.begin()+);
  20. else if(op==) printf("%d\n",v[x-]);
  21. else if(op==) printf("%d\n",*--lower_bound(v.begin(),v.end(),x));
  22. else if(op==) printf("%d\n",*upper_bound(v.begin(),v.end(),x));
  23. }
  24. return ;
  25. }
  26. /*
  27. 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
  28. 1. 插入x数
  29. 2. 删除x数(若有多个相同的数,因只删除一个)
  30. 3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
  31. 4. 查询排名为x的数
  32. 5. 求x的前驱(前驱定义为小于x,且最大的数)
  33. 6. 求x的后继(后继定义为大于x,且最小的数)
  34. */

Balanced Tree By vector

图论

  • Floyd算法。复杂度$O(n^3)$
  1. memset(dis,0x3f,sizeof(dis));
  2. for(int i=;i<=v;i++) dis[i][i]=,dis[][i]=;//这一步很重要
  3. for(int i=;i<=e;i++)
  4. {
  5. int x=,y=,z=;
  6. scanf("%d%d%d",&x,&y,&z);
  7. dis[x][y]=min(dis[x][y],z);
  8. dis[y][x]=min(dis[y][x],z);
  9. }
  10. for(int kk=;kk<=v;kk++)
  11. for(int i=;i<=v;i++)
  12. for(int j=;j<=v;j++)
  13. dis[i][j]=min(dis[i][j],dis[i][kk]+dis[kk][j]);

floyd

  • Dijkstra+堆优化。复杂度$O(mlogn)$。稠密图优。好像不能用来跑最长路诶(
  1. void dijkstra()
  2. {
  3. priority_queue<pair<int,int> >q;
  4. memset(dis,0x3f,sizeof(dis));
  5. dis[s]=;q.push(make_pair(,s));
  6. while(!q.empty())
  7. {
  8. int u=q.top().second;q.pop();
  9. if(vis[u]) continue;
  10. vis[u]=;
  11. for(int i=head[u];i;i=edge[i].next)
  12. {
  13. int v=edge[i].to;
  14. if(dis[v]>dis[u]+edge[i].val)
  15. {
  16. dis[v]=dis[u]+edge[i].val;
  17. q.push(make_pair(-dis[v],v));
  18. }
  19. }
  20. }
  21. }

Dijkstra+Heap

  • spfa过世算法复杂度理解为$O(nm)$。但稀疏图$O(km)$。
  1. void spfa()
  2. {
  3. memset(dis,0x3f,sizeof(dis));
  4. queue<int>q;
  5. q.push(s),vis[s]=,dis[s]=;
  6. while(!q.empty())
  7. {
  8. int u=q.front();q.pop();
  9. vis[u]=;
  10. for(int i=head[u];i;i=edge[i].next)
  11. {
  12. int v=edge[i].to;
  13. if(dis[v]>dis[u]+edge[i].val)
  14. {
  15. dis[v]=dis[u]+edge[i].val;
  16. if(!vis[v]) q.push(v),vis[v]=;
  17. }
  18. }
  19. }
  20. }

spfa

  • 判断树上两路径是否相交

*  题目:LuoguP3398仓鼠找sugar / 计蒜客NOIP提高组模拟一试T2 敌对势力 / hihocoder 11D(题目找不到了==可以看这位dalao的博客

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<queue>
  4. #include<cmath>
  5. #define maxn 100090
  6.  
  7. using namespace std;
  8.  
  9. int n,m,tot,t;
  10. int head[maxn],d[maxn],f[maxn][];
  11. struct node{
  12. int to,next;
  13. }edge[maxn*];
  14.  
  15. void add(int x,int y)
  16. {
  17. edge[++tot].to=y;
  18. edge[tot].next=head[x];
  19. head[x]=tot;
  20. }
  21.  
  22. void LCA_prework()
  23. {
  24. queue<int>q;
  25. q.push();d[]=;
  26. while(!q.empty())
  27. {
  28. int u=q.front();q.pop();
  29. for(int i=head[u];i;i=edge[i].next)
  30. {
  31. int v=edge[i].to;
  32. if(d[v]) continue;
  33. d[v]=d[u]+;
  34. f[v][]=u;
  35. for(int j=;j<=t;j++)
  36. f[v][j]=f[f[v][j-]][j-];
  37. q.push(v);
  38. }
  39. }
  40. }
  41.  
  42. int LCA(int x,int y)
  43. {
  44. if(d[x]>d[y]) swap(x,y);
  45. for(int i=t;i>=;i--)
  46. if(d[f[y][i]]>=d[x]) y=f[y][i];
  47. if(x==y) return x;
  48. for(int i=t;i>=;i--)
  49. if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
  50. return f[x][];
  51. }
  52.  
  53. int main()
  54. {
  55. scanf("%d%d",&n,&m);
  56. t=log2(n)+;
  57. for(int i=;i<=n-;i++)
  58. {
  59. int x=,y=;
  60. scanf("%d%d",&x,&y);
  61. add(x,y);add(y,x);
  62. }
  63. LCA_prework();
  64. for(int i=;i<=m;i++)
  65. {
  66. int a=,b=,c=,e=;
  67. scanf("%d%d%d%d",&a,&b,&c,&e);
  68. int Chemist=LCA(a,b);
  69. int cellur=LCA(c,e);
  70. if(Chemist==cellur)
  71. {
  72. printf("NO\n");
  73. continue;
  74. }
  75. if(d[Chemist]>d[cellur])
  76. {
  77. if(LCA(Chemist,c)==Chemist||LCA(Chemist,e)==Chemist)
  78. {
  79. printf("NO\n");
  80. continue;
  81. }
  82. else
  83. {//没有相交输出yes
  84. printf("YES\n");
  85. continue;
  86. }
  87. }
  88. else
  89. {
  90. if(LCA(cellur,a)==cellur||LCA(cellur,b)==cellur)
  91. {
  92. printf("NO\n");
  93. continue;
  94. }
  95. else
  96. {
  97. printf("YES\n");
  98. continue;
  99. }
  100. }
  101. }
  102.  
  103. return ;
  104. }
  • 最短路计数
  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<queue>
  4. #include<cstring>
  5.  
  6. using namespace std;
  7. typedef long long ll;
  8.  
  9. int n,m,fake;
  10. int vis[],dis[];
  11. ll f[];
  12. int e[][];
  13.  
  14. void spfa()
  15. {
  16. memset(dis,,sizeof(dis));
  17. fake=dis[];
  18. queue<int>q;
  19. q.push();vis[]=;dis[]=;f[]=;
  20. while(!q.empty())
  21. {
  22. int u=q.front();q.pop();
  23. vis[u]=;
  24. if(u==n) continue;
  25. for(int i=;i<=n;i++)
  26. {
  27. if(dis[i]==dis[u]+e[u][i])
  28. f[i]+=f[u];
  29. if(dis[i]>dis[u]+e[u][i])
  30. {
  31. dis[i]=dis[u]+e[u][i];
  32. f[i]=f[u];
  33. }
  34. if(f[i]&&!vis[i]) vis[i]=,q.push(i);
  35. }
  36. f[u]=;
  37. }
  38. }
  39.  
  40. int main()
  41. {
  42. scanf("%d%d",&n,&m);
  43. memset(e,,sizeof(e));
  44. for(int i=;i<=m;i++)
  45. {
  46. int x=,y=,z=;
  47. scanf("%d%d%d",&x,&y,&z);
  48. e[x][y]=min(e[x][y],z);
  49. }
  50. spfa();
  51. if(fake==dis[n]) printf("No answer");
  52. else printf("%d %lld",dis[n],f[n]);
  53. return ;
  54. }

以上是过世算法$spfa$,现在我来为大家表演一下$dijkstra$。(搬运逛公园的30部分分)dij不用清空,非常优秀。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<queue>
  4. #include<cstring>
  5. #define maxn 100090
  6.  
  7. using namespace std;
  8. typedef long long ll;
  9.  
  10. int T,n,m,k,tot;
  11. int head[maxn];
  12. bool vis[maxn];
  13. ll moder,f[maxn],dis[maxn];
  14. struct node{
  15. int to,next,val;
  16. }edge[maxn<<];
  17.  
  18. void add(int x,int y,int z)
  19. {
  20. edge[++tot].to=y;
  21. edge[tot].next=head[x];
  22. head[x]=tot;
  23. edge[tot].val=z;
  24. }
  25.  
  26. void Clear()
  27. {
  28. tot=;
  29. memset(head,,sizeof(head));
  30. memset(vis,,sizeof(vis));
  31. memset(f,,sizeof(f));
  32. }
  33.  
  34. void dijkstra()
  35. {
  36. priority_queue<pair<ll,int> >q;
  37. for(int i=;i<=n;i++) dis[i]=3e9;
  38. q.push(make_pair(,));dis[]=;f[]=;
  39. while(!q.empty())
  40. {
  41. int u=q.top().second;q.pop();
  42. if(vis[u]) continue;
  43. vis[u]=;
  44. for(int i=head[u];i;i=edge[i].next)
  45. {
  46. int v=edge[i].to;
  47. if(dis[v]>dis[u]+edge[i].val)
  48. {
  49. dis[v]=dis[u]+edge[i].val;
  50. q.push(make_pair(-dis[v],v));
  51. (f[v]=f[u])%=moder;
  52. }
  53. else if(dis[v]==dis[u]+edge[i].val)
  54. (f[v]+=f[u])%=moder;
  55. }
  56. }
  57. }
  58.  
  59. int main()
  60. {
  61. scanf("%d",&T);
  62. while(T--)
  63. {
  64. scanf("%d%d%d%lld",&n,&m,&k,&moder);
  65. for(int i=;i<=m;i++)
  66. {
  67. int x=,y=,z=;
  68. scanf("%d%d%d",&x,&y,&z);
  69. add(x,y,z);
  70. }
  71. dijkstra();
  72. // if(dis[n]==3e9) printf("-1");
  73. printf("%lld\n",f[n]);
  74. //for(int i=1;i<=n;i++) printf("%lld ",dis[i]);
  75. Clear();
  76. }
  77. return ;
  78. }

Counting

  • kruskal算法求最小生成树:基于边。比较好理解,先对所有边进行排序,用并查集维护联通关系。复杂度为$O(mlogm)$。(其实不用找到n-1条边就退出...)
  1. /*
  2. 最小生成树Kruskal算法
  3. 快排权值+并查集看是否连通
  4. */
  5. #include<cstdio>
  6. #include<algorithm>
  7.  
  8. using namespace std;
  9.  
  10. int n,m,cnt,ans;
  11. int fa[];
  12. struct node{
  13. int f,t,w;
  14. }edge[];
  15.  
  16. bool cmp(node a,node b)
  17. {
  18. return a.w<b.w;
  19. }
  20.  
  21. int getf(int x)
  22. {
  23. if(x==fa[x]) return x;
  24. return fa[x]=getf(fa[x]);
  25. }
  26.  
  27. int main()
  28. {
  29. scanf("%d%d",&n,&m);
  30. for(int i=;i<=m;i++)
  31. scanf("%d%d%d",&edge[i].f,&edge[i].t,&edge[i].w);
  32. for(int i=;i<=n;i++) fa[i]=i;
  33. sort(edge+,edge++m,cmp);
  34. for(int i=;i<=m;i++)
  35. {
  36. if(cnt==n-) break;
  37. int pp=getf(edge[i].f);
  38. int qq=getf(edge[i].t);
  39. if(pp==qq) continue;
  40. fa[qq]=pp;
  41. cnt++;
  42. ans+=edge[i].w;
  43. }
  44. if(cnt<n-) printf("orz");
  45. else printf("%d\n",ans);
  46. return ;
  47. }

Kruskal

  • Prim算法求最小生成树:基于点,逐步扩展。随便找一个点作为起点,设$dis$为添加了这个点需要增加的边权,然后每次在尚未被进入生成树的节点中寻找最小的$dis$,记录它的位置,这一次就把他加入生成树,并更新其他点的$dis$。复杂度$O(n^2)$。注意是否$vis$。
  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #define maxn 5090
  5.  
  6. using namespace std;
  7. typedef long long ll;
  8.  
  9. int n,m,tot;
  10. ll ans;
  11. int head[maxn],dis[maxn],vis[maxn];
  12. struct node{
  13. int to,next,val;
  14. }edge[];
  15.  
  16. void add(int x,int y,int z)
  17. {
  18. edge[++tot].to=y;
  19. edge[tot].next=head[x];
  20. head[x]=tot;
  21. edge[tot].val=z;
  22. }
  23.  
  24. void prim()
  25. {
  26. memset(dis,,sizeof(dis));
  27. dis[]=;
  28. for(int k=;k<=n;k++)
  29. {
  30. int u=-,sta=0x3f3f3f3f;
  31. for(int i=;i<=n;i++)
  32. if(dis[i]<sta&&!vis[i]) sta=dis[i],u=i;
  33. if(u==-) {printf("orz\n");exit();}
  34. ans+=dis[u];
  35. vis[u]=;
  36. for(int i=head[u];i;i=edge[i].next)
  37. {
  38. int v=edge[i].to;
  39. if(vis[v]) continue;
  40. dis[v]=min(dis[v],edge[i].val);
  41. }
  42. }
  43. }
  44.  
  45. int main()
  46. {
  47. scanf("%d%d",&n,&m);
  48. for(int i=;i<=m;i++)
  49. {
  50. int x=,y=,z=;
  51. scanf("%d%d%d",&x,&y,&z);
  52. add(x,y,z);add(y,x,z);
  53. }
  54. prim();
  55. printf("%d\n",ans);
  56. return ;
  57. }

Prim

  • 树的直径方法一:两遍bfs/dfs【不能处理有负权边情况】【记录路径】
  1. int bfs(int x)
  2. {
  3. queue<int>q;
  4. memset(d,0x3f,sizeof(d));
  5. memset(pre,,sizeof(pre));
  6. fake=d[];
  7. q.push(x);d[x]=;
  8. while(!q.empty())
  9. {
  10. int u=q.front();q.pop();
  11. for(int i=head[u];i;i=edge[i].next)
  12. {
  13. int v=edge[i].to;
  14. if(d[v]==fake) q.push(v),pre[v]=i,d[v]=d[u]+;
  15. }
  16. }
  17. int top=x;
  18. for(int i=;i<=n;i++)
  19. if(d[i]>d[top]) top=i;
  20. return top;
  21. }
  22. int get_d()
  23. {
  24. p=bfs();
  25. p=bfs(p);
  26. return d[p];
  27. }

Tree's Diameter/BFS

  • 树的直径方法二:树形dp
  1. void Treedp(int u)
  2. {
  3. vis[u]=;
  4. for(int i=head[u];i;i=edge[i].next)
  5. {
  6. int v=edge[i].to;
  7. if(vis[v]) continue;
  8. Treedp(v);
  9. ans=max(ans,f[x]+f[y]+edge[i].val)
  10. f[x]=max(f[x],f[y]+edge[i].val);
  11. }
  12. }

Tree's Diameter/Treedp

  • 强连通分量/缩点(in有向图)
  1. void tarjan(int u)
  2. {
  3. dfn[u]=low[u]=++dfs_clock;
  4. st.push(u);
  5. for(int i=head[u];i;i=edge[i].next)
  6. {
  7. int v=edge[i].to;
  8. if(!dfn[v])
  9. {
  10. tarjan(v);
  11. low[u]=min(low[u],low[v]);
  12. }
  13. else if(!scc[v]) low[u]=min(low[u],dfn[v]);
  14. }
  15. if(low[u]==dfn[u])
  16. {
  17. scc_cnt++;
  18. while()
  19. {
  20. int x=st.top();st.pop();
  21. scc[x]=scc_cnt;
  22. if(x==u) break;
  23. }
  24. }
  25. }
  26. —————————————————————————————————————
  27. for(int i=;i<=n;i++)//在主程序中
  28. if(!dfn[i]) tarjan(i);
  29. for(int x=;x<=n;x++)
  30. for(int i=head[x];i;i=edge[i].next)
  31. {
  32. int y=edge[i].to;
  33. if(scc[x]!=scc[y])
  34. ADD(scc[x],scc[y]);
  35. }

tarjan1

  • 树上倍增求LCA

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<queue>
  4. #include<cmath>
  5. #define maxn 500090
  6.  
  7. using namespace std;
  8.  
  9. int n,m,s,tot,t;
  10. int d[maxn],head[maxn],f[maxn][];
  11. struct node{
  12. int to,next;
  13. }edge[maxn<<];
  14.  
  15. void add(int x,int y)
  16. {
  17. edge[++tot].to=y;
  18. edge[tot].next=head[x];
  19. head[x]=tot;
  20. }
  21.  
  22. void init()
  23. {
  24. queue<int>q;
  25. q.push(s);d[s]=;
  26. while(!q.empty())
  27. {
  28. int u=q.front();q.pop();
  29. for(int i=head[u];i;i=edge[i].next)
  30. {
  31. int v=edge[i].to;
  32. if(d[v]) continue;
  33. d[v]=d[u]+;
  34. f[v][]=u;
  35. for(int j=;j<=t;j++)
  36. f[v][j]=f[f[v][j-]][j-];
  37. q.push(v);
  38. }
  39. }
  40. }
  41.  
  42. int lca(int x,int y)
  43. {
  44. if(d[x]<d[y]) swap(x,y);
  45. for(int i=t;i>=;i--)
  46. if(d[f[x][i]]>=d[y]) x=f[x][i];
  47. if(x==y) return x;
  48. for(int i=t;i>=;i--)
  49. if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
  50. return f[x][];
  51. }
  52.  
  53. int main()
  54. {
  55. scanf("%d%d%d",&n,&m,&s);
  56. t=log2(n)+;
  57. for(int i=;i<=n-;i++)
  58. {
  59. int x=,y=;
  60. scanf("%d%d",&x,&y);
  61. add(x,y),add(y,x);
  62. }
  63. init();
  64. for(int i=;i<=m;i++)
  65. {
  66. int x=,y=;
  67. scanf("%d%d",&x,&y);
  68. printf("%d\n",lca(x,y));
  69. }
  70. return ;
  71. }

LCA

字符串

  • $trie$树
  1. tot=;
  2. void insert()
  3. {
  4. int p=;
  5. int len=strlen(tmp+);
  6. for(int i=;i<=len;i++)
  7. {
  8. int qwq=tmp[i]-'';
  9. if(!trie[p][qwq]) trie[p][qwq]=++tot;
  10. p=trie[p][qwq];
  11. }
  12. }

trie--insert

  • 最小表示法
  1. void work()
  2. {
  3. n=strlen(str+);ans=;
  4. for(int i=;i<=n;i++) str[n+i]=str[i];
  5. int i=,j=,k;
  6. while(i<=n&&j<=n)
  7. {
  8. for(k=;k<=n&&str[i+k]==str[j+k];k++);
  9. if(k>=n) break;
  10. if(str[i+k]>str[j+k])
  11. {i=i+k+;if(i==j) i++;}
  12. else
  13. {j=j+k+;if(i==j) j++;}
  14. }
  15. ans=min(i,j);
  16. printf("%d\n",ans);
  17. }
  18. //注意数组开二倍+

Minimal Expression

其他技巧

  1. srand(time(NULL));
  • 生成数据的批处理文件($bat$)
  1. @echo off
  2. :loop
  3.  
  4. rand.exe
  5.  
  6. baoli.exe
  7.  
  8. sol.exe
  9.  
  10. fc baoli.out sol.out
  11.  
  12. if not errorlevel goto loop
  13.  
  14. pause
  15.  
  16. goto loop

dp.bat

  • 生成数据
  1. int random(int lim)
  2. {
  3. return (unsigned long long)rand()*rand()%lim;
  4. }
  5.  
  6. 调用时:int x=random()+;

rand

看到小数据范围:暴搜 全排列 二进制枚举  状压

$O(n^3)$:考虑枚举区间?

NOIp知识集合 By cellur925的更多相关文章

  1. python易错知识集合

    本篇用于记录在写leetcode时遇到的python易错知识. 2019.8.29 1.Python range() 函数用法: range(start, stop[, step]) start: 计 ...

  2. Java基础知识➣集合整理(三)

    概述 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个层次. 实现(类) ...

  3. Java基础知识--集合

    集合类 数组和集合的比较:数组可以存储对象,也可以存储基本数据类型,但是缺点就是长度固定,不能改变:集合长度是可变的,但是集合只能存储对象,集合可以存储不同类型的对象. Java容器类库一共有两种主要 ...

  4. 面试基础知识集合(python、计算机网络、操作系统、数据结构、数据库等杂记)

    python python _.__.__xx__之间的差别 python中range.xrange和randrange的区别 python中 =.copy.deepcopy的差别 python 继承 ...

  5. python知识集合

    1.list list是一种有序的集合 例子:classmates = ['Michael', 'Bob', 'Tracy']; 方法:1. len len(classmates) //3 2.app ...

  6. python基础知识-集合,列表,元组间的相互装换

    在python中列表,元祖,集合间可以进行相互转化, def main(): set1={'hello','good','banana','zoo','Python','hello'} print(l ...

  7. cocopods 知识集合 及 一个 好的 国外iOS技术翻译站

    http://www.exiatian.com/cocoapods%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E5%8F%8A%E9%85%8D%E7%BD%AE%E7% ...

  8. 从壹开始 [ Id4 ] 之二║ 基础知识集合 & 项目搭建一

    前言 哈喽大家又见面啦,感觉好久没更新了,这几天看了一本书<解忧杂货铺>,嗯挺好的,推荐一下

  9. js数组相关知识集合

    一.js数组快速排序 <script type="text/javascript"> var arr = [1, 2, 3, 54, 22, 1, 2, 3]; fun ...

随机推荐

  1. 吴恩达机器学习笔记(二) —— Logistic回归

    主要内容: 一.回归与分类 二.Logistic模型即sigmoid function 三.decision boundary 决策边界 四.cost function 代价函数 五.梯度下降 六.自 ...

  2. Module.exports和exports的区别

    原文链接: https://www.ycjcl.cc/2017/02/10/module-exportshe-exportsde-qu-bie/ 学习Seajs时,看到了exports.doSomet ...

  3. matlab之flipud()函数

    此函数实现矩阵的上下翻转.fliplw()实现左右旋转. 举例: a =[1 2;3 4;5 6] flipud(a)的结果: 5 6 3 4 1 2 fliplr(a)的结果: 2 1 4 3 6 ...

  4. HDU 4652 Dice:期望dp(成环)【错位相减】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4652 题意: 给你一个有m个面的骰子. 两种询问: (1)"0 m n": “最后 ...

  5. laravel 在apache或nginx的配置

    laravel 下载后,如何运行起来呢,根据自己的应用,记录了几个关键点: 1.apache 配置: 打开http.conf文件,将mod_rewrite前面的#去掉(启用重写模块): 2.nginx ...

  6. tensorflow 线性回归 iris

    线性拟合

  7. 写个sleep玩玩

    static void sig_when_weakup(int no){ printf("weakup weakup\n"); longjmp(buf, ); } void wea ...

  8. leetcode 304. Range Sum Query 2D - Immutable(递推)

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  9. ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)

    Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc&quo ...

  10. poj1050最大矩阵和——暴力枚举

    题目:http://poj.org/problem?id=1050 s[i][j]数组记录以点(i,j)为右下角.(1,1)为左上角的子矩阵内部和: 枚举子矩阵左上角和右下角,取最大值即可. 代码如下 ...