线段树
note : 如果要区间赋值为0要注意mark不要用0作为无标记
/************************************************ *Author : lrj124 *Created Time : 2018.11.05.16:31 *Mail : [email protected] *Problem : seg ************************************************/ #includeusing namespace std; const int maxn = 100000 + 10; int n,m; struct seg { long long sum; int l,r,mark; }tree[maxn<<2]; inline void pushup(int root) { tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum; } inline void pushdown(int root) { if (tree[root].mark) { tree[root<<1].mark += tree[root].mark; tree[root<<1].sum += tree[root].mark*(tree[root<<1].r-tree[root<<1].l+1); tree[root<<1|1].mark += tree[root].mark; tree[root<<1|1].sum += tree[root].mark*(tree[root<<1|1].r-tree[root<<1|1].l+1); tree[root].mark = 0; } } inline void build(int l,int r,int root) { tree[root].l = l; tree[root].r = r; if (l == r) { scanf("%lld",&tree[root].sum); return; } int mid = l+r>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); pushup(root); } inline void update(int l,int r,int ql,int qr,int root,long long x) { if (r < ql || l > qr) return; if (ql <= l && r <= qr) { tree[root].sum += x*(r-l+1); tree[root].mark += x; return; } pushdown(root); int mid = l+r>>1; update(l,mid,ql,qr,root<<1,x); update(mid+1,r,ql,qr,root<<1|1,x); pushup(root); } inline long long query(int l,int r,int ql,int qr,int root) { if (r < ql || l > qr) return 0; if (ql <= l && r <= qr) return tree[root].sum; pushdown(root); int mid = l+r>>1; return query(l,mid,ql,qr,root<<1)+query(mid+1,r,ql,qr,root<<1|1); } int main() { //freopen("seg.in","r",stdin); //freopen("seg.out","w",stdout); scanf("%d%d",&n,&m); build(1,n,1); while (m--) { int op,l,r; long long x; scanf("%d%d%d",&op,&l,&r); if (op == 1) { scanf("%lld",&x); update(1,n,l,r,1,x); } else printf("%lld\n",query(1,n,l,r,1)); } //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }
树链剖分
note : 如果维护的是边权的话在update和query的最后一句num[u]改为num[u]+1
/************************************************ *Author : lrj124 *Created Time : 2018.11.05.17:03 *Mail : [email protected] *Problem : tcd ************************************************/ #includeusing namespace std; const int maxn = 100000 + 10; int cnt,n,m,rt,p,val[maxn],dep[maxn],father[maxn],top[maxn],size[maxn],son[maxn],Map[maxn],num[maxn]; vector edge[maxn]; inline void dfs1(int now,int fa) { dep[now] = dep[fa]+1; father[now] = fa; size[now] = 1; for (size_t i = 0;i < edge[now].size();i++) if (edge[now][i] ^ fa) { dfs1(edge[now][i],now); size[now] += size[edge[now][i]]; if (size[edge[now][i]] > size[son[now]]) son[now] = edge[now][i]; } } inline void dfs2(int now,int ntop) { num[now] = ++cnt; Map[num[now]] = now; top[now] = ntop; if (son[now]) dfs2(son[now],ntop); for (size_t i = 0;i < edge[now].size();i++) if (edge[now][i] ^ father[now] && edge[now][i] ^ son[now]) dfs2(edge[now][i],edge[now][i]); } struct seg { long long sum,l,r,mark; } tree[maxn<<2]; inline void pushup(int root) { tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum; } inline void pushdown(int root) { if (tree[root].mark) { tree[root<<1].mark += tree[root].mark; tree[root<<1|1].mark += tree[root].mark; tree[root<<1].sum += tree[root].mark*(tree[root<<1].r-tree[root<<1].l+1); tree[root<<1|1].sum += tree[root].mark*(tree[root<<1|1].r-tree[root<<1|1].l+1); tree[root].mark = 0; } } inline void build(int l,int r,int root) { tree[root].l = l; tree[root].r = r; if (l == r) { tree[root].sum = val[Map[l]]; return; } int mid = l+r>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); pushup(root); } inline void update(int l,int r,int ql,int qr,int root,int x) { if (r < ql || l > qr) return; if (ql <= l && r <= qr) { tree[root].sum += x*(r-l+1); tree[root].mark += x; return; } pushdown(root); int mid = l+r>>1; update(l,mid,ql,qr,root<<1,x); update(mid+1,r,ql,qr,root<<1|1,x); pushup(root); } inline long long query(int l,int r,int ql,int qr,int root) { if (r < ql || l > qr) return 0; if (ql <= l && r <= qr) return tree[root].sum; int mid = l+r>>1; pushdown(root); return query(l,mid,ql,qr,root<<1)+query(mid+1,r,ql,qr,root<<1|1); } inline void updateroad(int u,int v,long long x) { while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u,v); update(1,n,num[top[u]],num[u],1,x); u = father[top[u]]; } if (dep[u] > dep[v]) swap(u,v); update(1,n,num[u],num[v],1,x); } inline long long queryroad(int u,int v) { long long sum = 0; while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u,v); sum = (sum+query(1,n,num[top[u]],num[u],1))%p; u = father[top[u]]; } if (dep[u] > dep[v]) swap(u,v); return (sum+query(1,n,num[u],num[v],1))%p; } int main() { //freopen("tcd.in","r",stdin); //freopen("tcd.out","w",stdout); scanf("%d%d%d%d",&n,&m,&rt,&p); for (int i = 1;i <= n;i++) scanf("%d",&val[i]); for (int i = 1,u,v;i < n;i++) { scanf("%d%d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } dfs1(rt,0); dfs2(rt,rt); build(1,n,1); while (m--) { int op,u,v; long long w; scanf("%d%d",&op,&u); if (op == 1) { scanf("%d%lld",&v,&w); updateroad(u,v,w); } if (op == 2) { scanf("%d",&v); printf("%lld\n",queryroad(u,v)); } if (op == 3) { scanf("%lld",&w); update(1,n,num[u],num[u]+size[u]-1,1,w); } if (op == 4) printf("%lld\n",query(1,n,num[u],num[u]+size[u]-1,1)%p); } //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }
Splay
splay旋转过程(旋转 $x$ , $y$ 为 $x$ 的父亲, $z$ 为 $y$ 的父亲) :
1. 把 $x$ 旋转为 $z$ 的儿子, $x$ 的父亲更新为 $y$
2. 把 $x$ 的儿子给 $y$ , $x$ 儿子的父亲更新为 $y$
3. $y$ 变为 $x$ 的儿子, $y$ 的父亲更新为 $x$
4. $pushup(y) \ , \ pushup(x)$ (先 $pushup(y)$ !)
......不想打了
二分图匹配
匈牙利:
note :
正确 :
match[edge[now][i]] = now;
错误 :
match[now] = edge[now][i];
/************************************************ *Author : lrj124 *Created Time : 2018.11.06.19:07 *Mail : [email protected] *Problem : hung ************************************************/ #includeusing namespace std; const int maxn = 1000 + 10; int n,m,e,match[maxn],ans; vector edge[maxn]; bool vis[maxn]; inline bool dfs(int now) { for (size_t i = 0;i < edge[now].size();i++) if (!vis[edge[now][i]]) { vis[edge[now][i]] = true; if (!match[edge[now][i]] || dfs(match[edge[now][i]])) { match[edge[now][i]] = now; return true; } } return false; } int main() { //freopen("hung.in","r",stdin); //freopen("hung.out","w",stdout); scanf("%d%d%d",&n,&m,&e); for (int i = 1,u,v;i <= e;i++) { scanf("%d%d",&u,&v); if (v > m) continue; edge[u].push_back(v); } for (int i = 1;i <= n;i++) { memset(vis,false,sizeof(vis)); if (dfs(i)) ans++; } printf("%d",ans); //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }
Dinic:
/************************************************ *Author : lrj124 *Created Time : 2018.11.06.20:19 *Mail : [email protected] *Problem : dinic ************************************************/ #includeusing namespace std; const int maxn = 1000000 + 10; const int INF = 9999999; int n,m,e,s,t,dep[maxn],first[maxn],edgecnt = -1; struct edge { int to,next,w; } eg[maxn]; inline void addedge(int u,int v,int w) { eg[++edgecnt] = (edge){v,first[u],w},first[u] = edgecnt; eg[++edgecnt] = (edge){u,first[v],0},first[v] = edgecnt; } queue Q; inline int bfs() { memset(dep,0,sizeof(dep)); Q.push(s); dep[s] = 1; while (!Q.empty()) { int now = Q.front(); Q.pop(); for (int i = first[now];~i;i = eg[i].next) if (eg[i].w > 0 && !dep[eg[i].to]) { Q.push(eg[i].to); dep[eg[i].to] = dep[now]+1; } } return dep[t]; } inline int dfs(int now,int flow) { int tmp = flow; if (now == t) return flow; for (int i = first[now];~i;i = eg[i].next) if (dep[eg[i].to] == dep[now]+1 && eg[i].w) { int f = dfs(eg[i].to,min(eg[i].w,tmp)); if (f > 0) { eg[i].w -= f; eg[i^1].w += f; tmp -= f; if (!tmp) break; } } return flow-tmp; } inline int dinic() { int ans = 0; while (bfs()) ans += dfs(s,INF); return ans; } int main() { //freopen("dinic.in","r",stdin); //freopen("dinic.out","w",stdout); memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&m,&e); for (int i = 1,u,v;i <= e;i++) { scanf("%d%d",&u,&v); if (v > m) continue; v += n; addedge(u,v,1); } s = n+m+1; t = n+m+2; for (int i = 1;i <= n;i++) addedge(s,i,1); for (int i = 1;i <= m;i++) addedge(i+n,t,1); printf("%d",dinic()); //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }
网络最大流
note : 边的编号从0开始!
/************************************************ *Author : lrj124 *Created Time : 2018.11.06.19:25 *Mail : [email protected] *Problem : dinic ************************************************/ #includeusing namespace std; const int maxn = 10000 + 10; const int INF = 9999999; int n,m,s,t,dep[maxn],first[maxn],edgecnt = -1; struct edge { int to,next,w; } eg[maxn*20]; inline void addedge(int u,int v,int w) { eg[++edgecnt] = (edge){v,first[u],w},first[u] = edgecnt; eg[++edgecnt] = (edge){u,first[v],0},first[v] = edgecnt; } queue Q; inline int bfs() { memset(dep,0,sizeof(dep)); Q.push(s); dep[s] = 1; while (!Q.empty()) { int now = Q.front(); Q.pop(); for (int i = first[now];~i;i = eg[i].next) if (eg[i].w > 0 && !dep[eg[i].to]) { Q.push(eg[i].to); dep[eg[i].to] = dep[now]+1; } } return dep[t]; } inline int dfs(int now,int flow) { int tmp = flow; if (now == t) return flow; for (int i = first[now];~i;i = eg[i].next) if (dep[eg[i].to] == dep[now]+1 && eg[i].w) { int f = dfs(eg[i].to,min(eg[i].w,tmp)); if (f > 0) { eg[i].w -= f; eg[i^1].w += f; tmp -= f; if (!tmp) break; } } return flow-tmp; } inline int dinic() { int ans = 0; while (bfs()) ans += dfs(s,INF); return ans; } int main() { //freopen("dinic.in","r",stdin); //freopen("dinic.out","w",stdout); memset(first,-1,sizeof(first)); scanf("%d%d%d%d",&n,&m,&s,&t); for (int i = 1,u,v,w;i <= m;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } printf("%d",dinic()); //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }
扩展欧几里德
/************************************************ *Author : lrj124 *Created Time : 2018.11.09.12:43 *Mail : [email protected] *Problem : exgcd ************************************************/ #includeusing namespace std; typedef long long ll; inline ll exgcd(ll a,ll b,ll& x,ll& y) { if (!b) { x = 1; y = 0; return a; } int tmp = exgcd(b,a%b,y,x); y -= (a/b)*x; return tmp; } int main() { //freopen("exgcd.in","r",stdin); //freopen("exgcd.out","w",stdout); ll a,b,x,y; scanf("%lld%lld",&a,&b); exgcd(a,b,x,y); printf("%lld",(x+b)%b); return 0; }
有理数取余
如果p是质数可以用$\frac{a}{b} = a \times b^{p-2} \ mod \ p$
/************************************************ *Author : lrj124 *Created Time : 2018.11.09.12:43 *Mail : [email protected] *Problem : exgcd ************************************************/ #includeusing namespace std; const int MOD = 19260817; typedef long long ll; inline void read(ll &x) { int p = 1; char ch; while ((ch = getchar()) > '9' || ch < '0') if (ch == '-') p = -1; x = ch-'0'; while ((ch = getchar()) <= '9' && ch >= '0') x = (x*10+ch-'0')%MOD; x *= p; } inline ll exgcd(ll a,ll b,ll& x,ll& y) { if (!b) { x = 1; y = 0; return a; } int tmp = exgcd(b,a%b,y,x); y -= (a/b)*x; return tmp; } int main() { //freopen("exgcd.in","r",stdin); //freopen("exgcd.out","w",stdout); ll a = 0,b = 0,x,y; read(a),read(b); if (!b) { printf("Angry!"); return 0; } exgcd(b,MOD,x,y); printf("%lld",(x+MOD)%MOD*a%MOD); return 0; }
Dijkstra
单源最短路
/************************************************ *Author : lrj124 *Created Time : 2018.11.09.08:22 *Mail : [email protected] *Problem : dijksttra ************************************************/ #includeusing namespace std; const int maxn = 100000 + 10; int n,m,s,first[maxn],edgecnt; long long dis[maxn]; bool vis[maxn]; struct edge { int to,next,w; } eg[maxn*4]; inline void addedge(int u,int v,int w) { eg[++edgecnt] = (edge){v,first[u],w}; first[u] = edgecnt; } priority_queue > Q; inline void Dijkstra() { for (int i = 1;i <= n;i++) dis[i] = 2147483647; Q.push(make_pair(0,s)); dis[s] = 0; while (!Q.empty()) { int now = Q.top().second; Q.pop(); if (vis[now]) continue; vis[now] = true; for (int i = first[now];~i;i = eg[i].next) if (dis[eg[i].to] > dis[now]+eg[i].w) { dis[eg[i].to] = dis[now]+eg[i].w; Q.push(make_pair(-dis[eg[i].to],eg[i].to)); } } } int main() { //freopen("dijksttra.in","r",stdin); //freopen("dijksttra.out","w",stdout); memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&m,&s); for (int i = 1,u,v,w;i <= m;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } Dijkstra(); for (int i = 1;i <= n;i++) printf("%lld ",dis[i]); return 0; }
最短路计数
/************************************************ *Author : lrj124 *Created Time : 2018.11.09.08:39 *Mail : [email protected] *Problem : dijkstra ************************************************/ #includeusing namespace std; const int maxn = 1000000 + 10; const int MOD = 100003; int n,m,edgecnt,first[maxn]; long long dis[maxn],cnt[maxn]; bool vis[maxn]; struct edge { int to,next,w; } eg[maxn*4]; inline void addedge(int u,int v,int w) { eg[++edgecnt] = (edge){v,first[u],w}; first[u] = edgecnt; eg[++edgecnt] = (edge){u,first[v],w}; first[v] = edgecnt; } priority_queue > Q; inline void Dijkstra(int s) { for (int i = 1;i <= n;i++) dis[i] = 2147483647; Q.push(make_pair(0,s)); dis[s] = 0; cnt[s] = 1; while (!Q.empty()) { int now = Q.top().second; Q.pop(); if (vis[now]) continue; vis[now] = true; for (int i = first[now];~i;i = eg[i].next) if (dis[eg[i].to] > dis[now]+eg[i].w) { dis[eg[i].to] = dis[now]+eg[i].w; cnt[eg[i].to] = cnt[now]; Q.push(make_pair(-dis[eg[i].to],eg[i].to)); } else if (dis[eg[i].to] == dis[now]+eg[i].w) cnt[eg[i].to] = (cnt[eg[i].to]+cnt[now])%MOD; } } int main() { //freopen("dijkstra.in","r",stdin); //freopen("dijkstra.out","w",stdout); memset(first,-1,sizeof(first)); scanf("%d%d",&n,&m); for (int i = 1,u,v;i <= m;i++) { scanf("%d%d",&u,&v); addedge(u,v,1); } Dijkstra(1); for (int i = 1;i <= n;i++) printf("%lld\n",cnt[i]); return 0; }
LCA
倍增:
/************************************************ *Author : lrj124 *Created Time : 2018.11.06.17:36 *Mail : [email protected] *Problem : lca ************************************************/ #includeusing namespace std; const int maxn = 500000 + 10; int n,m,s,dep[maxn],father[maxn][30]; vector edge[maxn]; inline void dfs(int now,int fa) { dep[now] = dep[fa]+1; father[now][0] = fa; for (size_t i = 0;i < edge[now].size();i++) if (edge[now][i] ^ fa) dfs(edge[now][i],now); } inline void init() { for (int j = 1;j <= 20;j++) for (int i = 1;i <= n;i++) father[i][j] = father[father[i][j-1]][j-1]; } inline int lca(int u,int v) { if (dep[u] < dep[v]) swap(u,v); for (int i = 20;i >= 0;i--) if (dep[father[u][i]] >= dep[v]) u = father[u][i]; if (u == v) return u; for (int i = 20;i >= 0;i--) if (father[u][i] ^ father[v][i]) { u = father[u][i]; v = father[v][i]; } return father[u][0]; } int main() { scanf("%d%d%d",&n,&m,&s); for (int i = 1,u,v;i < n;i++) { scanf("%d%d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } dfs(s,0); init(); for (int u,v;m--;) { scanf("%d%d",&u,&v); printf("%d\n",lca(u,v)); } //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }
重链剖分:
/************************************************ *Author : lrj124 *Created Time : 2018.11.06.18:02 *Mail : [email protected] *Problem : lca ************************************************/ #includeusing namespace std; const int maxn = 500000 + 10; int n,m,s,father[maxn],dep[maxn],top[maxn],size[maxn],son[maxn]; vector edge[maxn]; inline void dfs1(int now,int fa) { dep[now] = dep[fa]+1; father[now] = fa; size[now] = 1; for (size_t i = 0;i < edge[now].size();i++) if (edge[now][i] ^ fa) { dfs1(edge[now][i],now); size[now] += size[edge[now][i]]; if (size[edge[now][i]] > size[son[now]]) son[now] = edge[now][i]; } } inline void dfs2(int now,int ntop) { top[now] = ntop; if (son[now]) dfs2(son[now],ntop); for (size_t i = 0;i < edge[now].size();i++) if (edge[now][i] ^ father[now] && edge[now][i] ^ son[now]) dfs2(edge[now][i],edge[now][i]); } inline int lca(int u,int v) { while (top[u] ^ top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u,v); u = father[top[u]]; } if (dep[u] > dep[v]) swap(u,v); return u; } int main() { //freopen("lca.in","r",stdin); //freopen("lca.out","w",stdout); scanf("%d%d%d",&n,&m,&s); for (int i = 1,u,v;i < n;i++) { scanf("%d%d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } dfs1(s,0); dfs2(s,s); for (int u,v;m--;) { scanf("%d%d",&u,&v); printf("%d\n",lca(u,v)); } //cerr << 1.0*clock()/CLOCKS_PER_SEC << endl; return 0; }