Rating:1945 | 1.建图 2.数字哈希 3.树分块 4.二分图最大匹配匈牙利算法 5.普通线段树 6.普通并查集 8.树链剖分(点权) 9.最小公倍数&最小公约数 10.树链剖分(边权) 11.组合数打表(求大量组合数) 12.费用流 13.伸展树 以下内容于[2018-08-23 21:13:22]补充 14.最大流 |
Rating:1945 | const int maxn = 200000 + 10; int n, m, first[maxn], sign; struct Edge { int to, w, next; } edge[maxn << 2]; void init() { memset(first, -1, sizeof(first)); sign = 0; } void add_edge(int u, int v, int w) { edge[sign].to = v; edge[sign].w = w; edge[sign].next = first[u]; first[u] = sign++; } |
Rating:1945 |
|
Rating:1945 | ///树分块 int top = 0,st[maxn],belong[maxn],root,b; void dfs(int now) { int now_top = top; for(int i = first[now]; ~i; i = edge[i].next) { int to = edge[i].to; dfs(to); if(top-now_top >= b) ///stack内元素大于b出栈 { ++type; while(top!=now_top) { belong[st[top--]] = root; } } } st[++top] = now; } int main() { b = sqrt(n); type = 0; dfs(1); while(top)belong[st[top--]] = root; ///stack内剩余元素加入最后一个块中 return 0; } |
Rating:1945 | ///二分图匈牙利算法 时间复杂度O(n*m),空间复杂度,O(n*m) int nx,ny; bool bmap[maxn][maxn]; ///图 bool bmask[maxn]; int cx[maxn],cy[maxn]; int findpath(int u) { int i,j; for(int i=1; i<=ny; i++) { if(bmap[u][i]&&!bmask[i]) { bmask[i]=1; if(cy[i]==-1||findpath(cy[i])) { cy[i]=u; cx[u]=i; return 1; } } } return 0; } int MaxMatch(int n,int m) { int res=0; nx = n,ny = m; for(int i=0; i<maxn; i++) cx[i]=-1,cy[i]=-1; memset(bmask,0,sizeof(bmask)); for(int i=1; i<=nx; i++) { if(cx[i]==-1) { for(int j=1; j<=ny; j++) bmask[j]=0; res+=findpath(i); } } return res; } |
Rating:1945 | ///普通线段树 struct node { int l,r; ll sum,lazy; } T[maxn*4]; ll ans=0,a[maxn]; void build(int v,int l,int r) { T[v].l=l,T[v].r=r,T[v].lazy = 0; if(l==r) { T[v].sum=a[l]; return ; } int mid = (l+r)>>1; build(v<<1,l,mid); build(v<<1|1,mid+1,r); T[v].sum = T[v<<1].sum+T[v<<1|1].sum; } void add(int v,int l,int r,ll value) { if(T[v].l==l&&T[v].r==r) { T[v].sum+=value*(r-l+1); T[v].lazy+=value; return ; } int mid=(T[v].l+T[v].r)>>1; if(T[v].lazy) { T[v<<1].sum += T[v].lazy * (T[v<<1].r - T[v<<1].l + 1); T[v<<1|1].sum += T[v].lazy * (T[v<<1|1].r - T[v<<1|1].l + 1); T[v<<1].lazy += T[v].lazy; T[v<<1|1].lazy += T[v].lazy; T[v].lazy=0; } if(r<=mid) { add(v<<1,l,r,value); } else { if(l>mid) { add(v<<1|1,l,r,value); } else { add(v<<1,l,mid,value); add(v<<1|1,mid+1,r,value); } } T[v].sum = T[v<<1].sum+T[v<<1|1].sum; } void query(int v,int l,int r) { if(T[v].l==l&&T[v].r==r) { ans += T[v].sum; return ; } int mid=(T[v].l+T[v].r)>>1; if(T[v].lazy) { T[v<<1].sum += T[v].lazy * (T[v<<1].r - T[v<<1].l + 1); T[v<<1|1].sum += T[v].lazy * (T[v<<1|1].r - T[v<<1|1].l + 1); T[v<<1].lazy += T[v].lazy; T[v<<1|1].lazy += T[v].lazy; T[v].lazy=0; } if(r<=mid) { query(v<<1,l,r); } else { if(l>mid) { query(v<<1|1,l,r); } else { query(v<<1,l,mid); query(v<<1|1,mid+1,r); } } T[v].sum = T[v<<1].sum+T[v<<1|1].sum; } |
Rating:1945 | ///普通并查集 int father[maxn]; void make_set(int n) { for(int i=0; i<=n; i++)father[i]=i; } int Find(int x) { int p,tmp; p = x; while(x != father[x]) x = father[x]; while(p!=x) { tmp = father[p]; father[p] = x; p = tmp; } return x; } int isSome(int x,int y) { if(Find(x)==Find(y)) { return 1; } return 0; } int Union(int x,int y) { int rx=Find(x),ry=Find(y); if(rx!=ry) { father[rx]=ry; } } |
Rating:1945 | ///树链剖分 int tim=0; int pos[N]; ///用来保存当前节点在线段树中的位置; int deep[N]; ///用来保存当前节点的深度; int tid[N]; ///用来保存树中每个节点剖分后的新编号; int son[N]; ///用来保存重儿子; int top[N]; ///用来保存当前节点的所在链的顶端节点; int size[N]; ///用来保存以x为根的子树节点个数; int fa[N]; ///用来保存当前节点的父亲; long long begi[N]; ///按树原来编号元素值 //建图 int first[N], sign; void init() { memset(first, -1, sizeof(first)); sign = 0; } void add_edge(int u, int v) { edge[sign].to = v; edge[sign].next = first[u]; first[u] = sign++; } //两次dfs void dfsfir(int u,int father,int dep) { fa[u]=father; deep[u]=dep; size[u]=1; for(int i=first[u]; ~i; i=edge[i].next) { int v=edge[i].to; if(v!=father) { dfsfir(v,u,dep+1); size[u]+=size[v]; if(son[u]==0||size[v]>size[son[u]])son[u]=v; } } } void dfsec(int u,int tp) { top[u]=tp; tid[u]=++tim; pos[tid[u]]=u; if(son[u]==0)return; dfsec(son[u],tp); for(int i=first[u]; ~i; i=edge[i].next) { int v=edge[i].to; if(v!=fa[u]&&v!=son[u])dfsec(v,v); } } //查询和 ///路径上点权和 long long findSum(int x,int y) { long long sum=0; int fx,fy; fx=top[x]; fy=top[y]; while(fx!=fy)//不在一条重链上,即非连续一段区间 { if(deep[fx]<deep[fy]) { swap(fx,fy); swap(x,y); } sum=(sum+QuerySum(1,tid[fx],tid[x])); x=fa[fx]; fx=top[x]; } if(deep[x]>deep[y]) swap(x,y);//同一条重链 return sum=(sum+QuerySum(1,tid[x],tid[y])); } ///区间更新 void treeUpdate(int x,int y,int z) { int fx,fy; fx=top[x]; fy=top[y]; while(fx!=fy)//不在一条重链上,即非连续一段区间 { if(deep[fx]<deep[fy]) { swap(fx,fy); swap(x,y); } add(1,tid[fx],tid[x],z); x=fa[fx]; fx=top[x]; } if(deep[x]>deep[y]) swap(x,y);//同一条重链 add(1,tid[x],tid[y],z); } ///线段树建树 void build(int v,int l,int r) { /* */ if(l==r) { T[v].Max = T[v].sum = begi[pos[l]]; return ; } /* */ } int main() { ///************ dfsfir(1,0,1); dfsec(1,1); ///************ ///更新x的值为y ///update(1,tid[x],y); } |
Rating:1945 | ///最小公倍数&最小公约数 ll GCD(ll a,ll b) { return b==0?a:GCD(b,a%b); } ll LCM(ll a,ll b) { return a*b/GCD(a,b); } |
Rating:1945 | ///树链剖分 边权 int son[maxn]; //表示该点重链的子节点 int num[maxn]; //表示以该点为根的子树的节点数量 int dep[maxn]; //表示该节点的深度 int fa[maxn]; //表示该节点的父亲节点 int vis[maxn]; //表示该节点在线段树中的编号 int top[maxn]; //表示这条重链的顶端节点 int edge[maxn][3]; int now; void dfs1(int u,int v,int step) //第一遍dfs求出son,fa,num,dep { dep[v]=step,num[v]=1,fa[v]=u; for(int i=first[v]; ~i; i=edge1[i].next) { int to=edge1[i].to; if(to!=u) { dfs1(v,to,step+1); num[v]+=num[to]; if(son[v]==-1||num[son[v]]<num[to]) { son[v]=to; } } } } void dfs2(int u,int v) // 第二遍dfs求出top和vis { top[v]=u,vis[v]=now++; if(son[v]==-1) return ; else dfs2(u,son[v]); for(int i=first[v]; ~i; i=edge1[i].next) { int to = edge1[i].to; if(to==fa[v]||to==son[v]) continue; dfs2(to,to); } } int Find(int y,int z) { int q,w; int ans = 0; q = top[y],w = top[z]; int f=0; while(q != w) //不在一条重链上,就爬树 { if(dep[q] < dep[w]) swap(q,w),swap(y,z); if(f==0) { ans = query(1,vis[q]+1,vis[y]+1); f=1; } else ans = max(ans,query(1,vis[q]+1,vis[y]+1)); y = fa[q]; q = top[y]; } if(y != z) //爬到一条重链上 { if(dep[y] > dep[z]) swap(y,z); if(f==0) { ans = query(1,vis[son[y]]+1,vis[z]+1); f=1; } else ans = max(ans,query(1,vis[son[y]]+1,vis[z]+1)); } return ans; } void update(int y,int z) { int q,w; q = top[y],w = top[z]; while(q != w) //不在一条重链上,就爬树 { if(dep[q] < dep[w]) swap(q,w),swap(y,z); update1(1,vis[q]+1,vis[y]+1); y = fa[q]; q = top[y]; } if(y != z) //爬到一条重链上 { if(dep[y] > dep[z]) swap(y,z); update1(1,vis[son[y]]+1,vis[z]+1); } } void init() { now=0; memset(son,-1,sizeof(son)); memset(tree,0,sizeof(tree)); } int main() { init(); init_edge(); scanf("%d",&n); for(int i=1; i<=n-1; i++) { scanf("%d%d%d",&edge[i][0],&edge[i][1],&edge[i][2]); add_edge(edge[i][0],edge[i][1],edge[i][2]); add_edge(edge[i][1],edge[i][0],edge[i][2]); } dfs1(1,1,1); dfs2(1,1); build(1,1,n); for(int i = 1; i <= n-1; i++) { if(dep[edge[i][0]] < dep[edge[i][1]]) swap(edge[i][0],edge[i][1]); update2(1,vis[edge[i][0]]+1,edge[i][2]); } ///区间查询,更新 printf("%d\n",Find(l,r)); update(l,r); } |