# NOIP2018赛前模板复习

## 线段树

note : 如果要区间赋值为0要注意mark不要用0作为无标记

/************************************************
*Author        :  lrj124
*Created Time  :  2018.11.05.16:31
*Mail          :  1584634848@qq.com
*Problem       :  seg
************************************************/
#include <bits/stdc++.h>
using 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          :  1584634848@qq.com
*Problem       :  tcd
************************************************/
#include <bits/stdc++.h>
using 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<int> 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);
}
if (op == 2) {
scanf("%d",&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          :  1584634848@qq.com
*Problem       :  hung
************************************************/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000 + 10;
int n,m,e,match[maxn],ans;
vector<int> 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          :  1584634848@qq.com
*Problem       :  dinic
************************************************/
#include <bits/stdc++.h>
using 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<int> 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;
}
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          :  1584634848@qq.com
*Problem       :  dinic
************************************************/
#include <bits/stdc++.h>
using 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<int> 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);
}
printf("%d",dinic());
//cerr << 1.0*clock()/CLOCKS_PER_SEC << endl;
return 0;
}

## 扩展欧几里德

/************************************************
*Author        :  lrj124
*Created Time  :  2018.11.09.12:43
*Mail          :  1584634848@qq.com
*Problem       :  exgcd
************************************************/
#include <bits/stdc++.h>
using 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;
}

## 有理数取余

/************************************************
*Author        :  lrj124
*Created Time  :  2018.11.09.12:43
*Mail          :  1584634848@qq.com
*Problem       :  exgcd
************************************************/
#include <bits/stdc++.h>
using namespace std;
const int MOD = 19260817;
typedef long long ll;
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;
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          :  1584634848@qq.com
*Problem       :  dijksttra
************************************************/
#include <bits/stdc++.h>
using 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<pair<long long,int> > 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);
}
Dijkstra();
for (int i = 1;i <= n;i++) printf("%lld ",dis[i]);
return 0;
}

### 最短路计数

/************************************************
*Author        :  lrj124
*Created Time  :  2018.11.09.08:39
*Mail          :  1584634848@qq.com
*Problem       :  dijkstra
************************************************/
#include <bits/stdc++.h>
using 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<pair<int,int> > 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);
}
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          :  1584634848@qq.com
*Problem       :  lca
************************************************/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500000 + 10;
int n,m,s,dep[maxn],father[maxn][30];
vector<int> 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          :  1584634848@qq.com
*Problem       :  lca
************************************************/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500000 + 10;
int n,m,s,father[maxn],dep[maxn],top[maxn],size[maxn],son[maxn];
vector<int> 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;
}
posted @ 2018-11-06 17:28 lrj124 阅读(...) 评论(...) 编辑 收藏