树链剖分:(来源:树的统计)
#include#define rint register int using namespace std; inline void read(int &A) { A=0;int B=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')B=-1;ch=getchar();} while(ch>='0'&&ch<='9'){A=(A<<3)+(A<<1)+ch-'0';ch=getchar();} A=A*B;return ; } int n,q,v[60004],w[30004],nxt[60004],first[30004],tot; int f[30004],d[30004],siz[30004],son[30004]; int id[30004],rk[30004],cnt,tp[30004],ans; char ch[13]; struct node{int k,mx;}t[30004<<2]; inline void build_line(int uu,int vv) { v[++tot]=vv,nxt[tot]=first[uu]; first[uu]=tot; } inline void dfs(int x,int fa,int dep) { f[x]=fa,d[x]=dep,siz[x]=1; for(rint i=first[x];i;i=nxt[i]) { int y=v[i];if(y==fa)continue; dfs(y,x,dep+1);siz[x]+=siz[y]; if(siz[y]>siz[son[x]])son[x]=y; } return ; } inline void Dfs(int x,int t) { tp[x]=t,id[x]=++cnt,rk[cnt]=x; if(!son[x])return ;Dfs(son[x],t); for(rint i=first[x];i;i=nxt[i]) if(v[i]!=son[x]&&v[i]!=f[x]) Dfs(v[i],v[i]); return ; } inline void update(int k) { t[k].k=t[k<<1].k+t[k<<1|1].k; t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx); return ; } inline void build(int k,int l,int r) { if(l==r){t[k].k=t[k].mx=w[rk[l]];return ;} int mid=(l+r)>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); update(k);return ; } inline int Qsum(int k,int l,int r,int L,int R) { if(L<=l&&r<=R)return t[k].k; int mid=(l+r)>>1,res=0; if(L<=mid)res+=Qsum(k<<1,l,mid,L,R); if(R>mid)res+=Qsum(k<<1|1,mid+1,r,L,R); return res; } inline int Qmax(int k,int l,int r,int L,int R) { if(L<=l&&r<=R)return t[k].mx; int mid=(l+r)>>1,res=-0x7fffffff; if(L<=mid)res=max(res,Qmax(k<<1,l,mid,L,R)); if(R>mid)res=max(res,Qmax(k<<1|1,mid+1,r,L,R)); return res; } inline void change(int k,int l,int r,int p,int dat) { if(l==r){t[k].k=t[k].mx=dat;return ;} int mid=(l+r)>>1; if(p<=mid)change(k<<1,l,mid,p,dat); else change(k<<1|1,mid+1,r,p,dat); update(k);return ; } inline int get_sum(int x,int y) { int Sum=0,fx=tp[x],fy=tp[y]; while(fx!=fy) { if(d[fx]>=d[fy]) { Sum+=Qsum(1,1,n,id[fx],id[x]); x=f[fx],fx=tp[x]; } else { Sum+=Qsum(1,1,n,id[fy],id[y]); y=f[fy],fy=tp[y]; } } if(id[x]<=id[y])Sum+=Qsum(1,1,n,id[x],id[y]); else Sum+=Qsum(1,1,n,id[y],id[x]); return Sum; } inline int get_max(int x,int y) { int Max=-0x7fffffff,fx=tp[x],fy=tp[y]; while(fx!=fy) { if(d[fx]>=d[fy]) { Max=max(Max,Qmax(1,1,n,id[fx],id[x])); x=f[fx],fx=tp[x]; } else { Max=max(Max,Qmax(1,1,n,id[fy],id[y])); y=f[fy],fy=tp[y]; } } if(id[x]<=id[y])Max=max(Max,Qmax(1,1,n,id[x],id[y])); else Max=max(Max,Qmax(1,1,n,id[y],id[x])); return Max; } int main() { // freopen("count1.in","r",stdin); // freopen("my.out","w",stdout); read(n); for(rint i=1,ST,EN;i i) { read(ST),read(EN); build_line(ST,EN); build_line(EN,ST); } for(rint i=1;i<=n;++i)read(w[i]); dfs(1,0,1);Dfs(1,1);build(1,1,n); read(q); for(rint i=1,uu,vv;i<=q;++i) { scanf("%s",ch); if(ch[0]=='C') { read(uu),read(vv); change(1,1,n,id[uu],vv); } else { ans=0;read(uu),read(vv); if(ch[1]=='M')ans=get_max(uu,vv); else ans=get_sum(uu,vv); printf("%d\n",ans); } } }
tarjan点双
inline void tarjan(int x) { dfn[x]=low[x]=++cnt;s.push(x); if(x==root && firsty[x]==0) { dcc[++totq].clear(); dcc[totq].push_back(x); return ; } int flag=0; for(rint i=firsty[x];i;i=edge[i].nxt) { int y=edge[i].v; if(!dfn[y]) { tarjan(y);low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]) { flag++; if(x!=root||flag>1)cut[x]=true; totq++;int z; dcc[totq].clear(); do{ z=s.top();s.pop(); dcc[totq].push_back(z); }while(z!=y); dcc[totq].push_back(x); } } else low[x]=min(low[x],dfn[y]); } }
二分图匹配(带注释)
int point(int u)//这个函数的作用是寻找增广路和更新cx,xy数组,如果找到了增广路,函数返回1,找不到,函数返回0。 { for(int v=1;v<=ny;v++)//依次遍历右边的所有顶点 { if(e[u][v]&&!visited[v])//条件一:左边的u顶点和右边的v顶点有连通边,条件二:右边的v顶点在没有被访问过,这两个条件必须同时满足 { visited[v]=1;//将v顶点标记为访问过的 if(cy[v]==-1||point(cy[v]))//条件一:右边的v顶点没有左边对应的匹配的点,条件二:以v顶点在左边的匹配点为起点能够找到一条增广路(如果能够到达条件二,说明v顶点在左边一定有对应的匹配点)。 { cx[u]=v;//更新cx,cy数组 cy[v]=u; return 1; } } } return 0;//如果程序到达了这里,说明对右边所有的顶点都访问完了,没有满足条件的。 }
中国剩余定理
LL exgcd(LL a,LL b,LL &x,LL &y) { if(!b) { x=1;y=0; return a; } LL res=exgcd(b,a%b,x,y); LL t=x; x=y; y=t-a/b*x; return res; } LL China() { LL m=1; LL res=0; LL x,y; for(rint i=1;i<=n;i++)m*=a[i]; for(rint i=1;i<=n;i++) { LL tmp=m/a[i]; exgcd(tmp,a[i],x,y); res=(res+tmp*x*b[i])%m; } res=(res+m)%m; return res; }