[关闭]
@suixinhita 2020-11-29T03:04:40.000000Z 字数 4740 阅读 455

连山程设复(预)习

ACM oi


首先先给自己写个目录好吧:

高级不推荐算法,一般出现在 T3 除非 T1 已经 A 了,T2 出不来正解再尝试。主要是要保证线段树和查询的正确性。

两个dfs和查询修改的代码。

  1. void dfs1(int u,int fat)
  2. {
  3. fa[u]=fat;
  4. dep[u]=dep[fat]+1;
  5. size[u]=1;
  6. for(int i=head[u];i;i=e[i].next)
  7. {
  8. int v=e[i].to;
  9. if(v!=fat)
  10. {
  11. dfs1(v,u);
  12. size[u]+=size[v];
  13. if(size[v]>size[son[u]]) son[u]=v;
  14. }
  15. }
  16. }
  17. void dfs2(int u,int tp)
  18. {
  19. top[u]=tp;
  20. pos[u]=++cntp;
  21. if(son[u]) dfs2(son[u],tp);
  22. for(int i=head[u];i;i=e[i].next)
  23. {
  24. int v=e[i].to;
  25. if(v!=fa[u]&&v!=son[u])
  26. dfs2(v,v);
  27. }
  28. }

查询修改(路径)

  1. int max_(int x,int y)
  2. {
  3. if(x==y) return v[x];
  4. int f1=top[x];
  5. int f2=top[y],l,r;
  6. int ans=-inf;
  7. while(f1!=f2)
  8. {
  9. if(dep[f1]<dep[f2])
  10. {
  11. swap(x,y);
  12. swap(f1,f2);
  13. }
  14. l=pos[f1],r=pos[x];
  15. ans=max(ans,T.query_max(l,r));
  16. x=fa[f1],f1=top[x];
  17. }
  18. if(dep[x]<dep[y]) swap(x,y);
  19. l=pos[y],r=pos[x];
  20. ans=max(ans,T.query_max(l,r));
  21. return ans;
  22. }

查询修改(子树)

其实就是一个区间修改,因为无论怎么进行轻重划分,子树肯定是一个连续的序列。
- 计算几何
- 数论
- 字符串
- KMP

  1. void get_next(char c[],int cl)
  2. {
  3. for(int i=2;i<=cl;++i)
  4. {
  5. int j=fail[i-1];///////////
  6. while(j&&c[i]!=c[j+1]) j=fail[j];
  7. if(c[i]==c[j+1]) j++;//////////
  8. fail[i]=j;
  9. }
  10. }
  11. void check(char f[],char c[],int fl,int cl)
  12. {
  13. get_next(c,cl);
  14. int j=0;
  15. for(int i=1;i<=fl;++i)
  16. { /////////不用找上一个字母的失配点
  17. while(j&&f[i]!=c[j+1]) j=fail[j];
  18. if(f[i]==c[j+1]) j++;
  19. if(j==cl) ans[++ans[0]]=i-cl+1;
  20. }
  21. }
  1. ll quick_pow(ll x,ll k)
  2. {
  3. ll an=1;
  4. for(ll i=k;i;i>>=1,x=x*x%B)
  5. if(i&1) an=an*x%B;
  6. return an;
  7. }

给个例题,包括转移矩阵的构造。
转移公式如下:

%

然后需要做的是构造 的矩阵,然后在 每一个%处变为 1.

给个板子。

  1. struct mar{
  2. ll c[51][51];
  3. mar friend operator *(mar a,mar b)
  4. {
  5. mar y;
  6. for(int i=0;i<k_;++i)
  7. for(int j=0;j<k_;++j)
  8. {
  9. y.c[i][j]=0;
  10. for(int k=0;k<k_;++k)
  11. (y.c[i][j]+=(a.c[i][k]*b.c[k][j]))%=p;
  12. }
  13. return y;
  14. }
  15. };
  16. mar quick_pow(mar x,ll c)
  17. {
  18. mar an;
  19. memset(an.c,0,sizeof(an.c));
  20. for(int i=0;i<k_;++i) an.c[i][i]=1;
  21. for(ll i=c;i;i>>=1,x=x*x)
  22. if(i&1)
  23. an=an*x;
  24. return an;
  25. }
  1. int find(int x)
  2. {
  3. if(fa[x]==x) return x;
  4. int an=find(fa[x]);
  5. off[x]=(off[x]+off[fa[x]])%m;
  6. return fa[x]=an;
  7. }
  1. struct data{
  2. int to,next,f;
  3. }e[M*M*2];////开边注意
  4. int head[N<<1],gs,n,m,e_;
  5. void add(int fr,int to,int f)
  6. {
  7. gs++,e[gs].to=to,e[gs].f=f,e[gs].next=head[fr],head[fr]=gs;
  8. gs++,e[gs].to=fr,e[gs].f=0,e[gs].next=head[to],head[to]=gs;
  9. }
  10. int now[N<<1],dis[N<<1],s,t;
  11. bool bfs()
  12. {
  13. memset(dis,-1,sizeof(dis));
  14. queue<int> q;
  15. dis[s]=0;q.push(s);
  16. while(!q.empty())
  17. {
  18. int u=q.front();q.pop();
  19. for(int i=head[u];i;i=e[i].next)
  20. {
  21. int v=e[i].to;
  22. if(dis[v]==-1&&e[i].f)
  23. dis[v]=dis[u]+1,q.push(v);
  24. }
  25. }
  26. if(dis[t]==-1) return 0;
  27. return 1;
  28. }
  29. int dfs(int u,int f)
  30. {
  31. if(u==t) return f;
  32. int su=0,ff;
  33. for(int i=now[u];i;i=e[i].next)
  34. {
  35. int v=e[i].to;
  36. if(dis[v]!=dis[u]+1) continue;////////不是小是加1
  37. ff=min(e[i].f,f);
  38. ff=dfs(v,ff);
  39. e[i].f-=ff,e[i^1].f+=ff;
  40. su+=ff;f-=ff;
  41. if(e[i].f) now[u]=i;///当前弧的更新不要忘。
  42. if(su==f) return su;//一个小优化
  43. }
  44. if(su==0) dis[u]=-1;
  45. return su;
  46. }
  47. int dinic()
  48. {
  49. int an=0;
  50. while(bfs())
  51. {
  52. for(int i=s;i<=t;++i) now[i]=head[i];
  53. an+=dfs(s,maxx);
  54. }
  55. return an;
  56. }
  1. const double eps=1e-10;
  2. double a,b,l,r;
  3. double f(double x)
  4. {
  5. return b*sqrt(1.0-(x*x)/(a*a));
  6. }
  7. double simp(double l,double r)
  8. {
  9. return (f(l)+4*f((l+r)/2)+f(r))*(r-l)/6.0;
  10. }
  11. double simpson(double l,double r)
  12. {
  13. double mid=(l+r)/2.0;
  14. double ans=simp(l,r);
  15. if(fabs(ans-simp(l,mid)-simp(mid,r))<eps) return ans;
  16. else return simpson(l,mid)+simpson(mid,r);
  17. }
  18. int main()
  19. {
  20. int t;
  21. scanf("%d",&t);
  22. while(t--)
  23. {
  24. scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
  25. double ans=simpson(l,r);
  26. printf("%0.3lf\n",ans*2);
  27. }
  28. return 0;
  29. }

树上dp,树上维护都需要用到,非常基础有用。比较稳妥的是倍增,然后比较狠的是树剖,不修改的是打死也不能写树剖的。

可以在里面嵌套 .

  1. void add(int fr,int to)
  2. {
  3. gs++;e[gs].to=to,e[gs].next=head[fr],head[fr]=gs;
  4. gs++;e[gs].to=fr,e[gs].next=head[to],head[to]=gs;
  5. }
  6. //双向边注意
  7. int dep[N],fa[N];
  8. bool vis[N];
  9. void dfs(int u,int f)
  10. {
  11. fa[u]=f;vis[u]=1;
  12. dep[u]=dep[f]+1;
  13. for(int i=head[u];i;i=e[i].next)
  14. {
  15. int v=e[i].to;
  16. if(!vis[v]) dfs(v,u);
  17. }
  18. }
  19. int anc[20][N];
  20. void init()
  21. {
  22. for(int i=1;i<=n;++i) anc[0][i]=fa[i];
  23. for(int i=1;i<=19;++i)
  24. for(int j=1;j<=n;++j)
  25. anc[i][j]=anc[i-1][anc[i-1][j]];
  26. }
  27. int query(int x,int y)
  28. {
  29. if(dep[x]<dep[y]) swap(x,y);
  30. int len=dep[x]; /////////// 和RMQ不同的地方。
  31. int lo=-1;
  32. while(len) len>>=1,lo++;
  33. for(int i=lo;i>=0;--i)
  34. if(dep[anc[i][x]]>=dep[y])
  35. x=anc[i][x];
  36. if(x==y) return x;/////
  37. for(int i=lo;i>=0;--i)
  38. if(anc[i][x]!=anc[i][y]) ///////和树剖一样
  39. x=anc[i][x],y=anc[i][y];
  40. return fa[x];
  41. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注