一个蒟蒻的板子们
刷不动题,但是又要提高自己的代码能力,码码板子提高一下代码能力吧。开了键盘记录器,每天看看自己敲了多少次键盘吧。
矩阵乘法与快速幂(LOJ #100)
#include<cstdio>
#include<vector>
using namespace std;
typedef vector<long long> vec;
typedef vector<vec> matrix;
typedef long long ll;
const ll mod = 1e9 + 7;
matrix mul(matrix &A,matrix &B) {
matrix C(A.size(),vec(B[0].size()));
for(int i = 0; i < int(A.size()); i++)
for(int k = 0; k < int(B.size()); k++)
for(int j = 0; j < int(B[0].size()); j++)
C[i][j] = (((C[i][j] + A[i][k] * B[k][j]) % mod) + mod) % mod;
// 一定要先加模数再取模,否则爆负数就凉了,模数一定要放在最外层,防止爆 long long.
return C;
}
matrix pow(matrix A, ll n) {
matrix B(A.size(), vec(A.size()));
for(int i=0; i < int(A.size()); i++) B[i][i]=1;
while(n) {
if(n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int n, p, m;
int main() {
scanf("%d%d%d",&n, &p, &m);
matrix A(n, vec(p));
matrix B(p, vec(m));
for(int i = 0; i < n; ++i)
for(int j = 0; j < p; ++j)
scanf("%lld", &A[i][j]);
for(int i = 0; i < p; ++i)
for(int j = 0; j < m; ++j)
scanf("%lld", &B[i][j]);
matrix C = mul(A, B);
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j)
printf("%lld ", C[i][j]);
puts("");
}
return 0;
}
树链剖分与线段树的区间加与查询(洛谷 P3384)
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;
template<typename T> inline void read(T &x) {
x = 0; T w = 1; char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') w = -1; ch = getchar();}
while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x *= w;
}
const int maxn = 100005;
vector<int> G[maxn];
typedef vector<int>::iterator Iter;
int w[maxn], wt[maxn], son[maxn], id[maxn], fa[maxn], dep[maxn], siz[maxn],
top[maxn], cnt, n, m, r, mod, a, b, k, x, y, z;
inline void add(int u, int v) {G[u].push_back(v);}
struct node {
int l, r, mid, len, sum, laz; node *ls, *rs;
} *root, MemPool[2 * maxn]; int MemCnt;
inline void alloc(node* &x) {x = MemPool + MemCnt++;}
inline void pushup(node *rt) {rt->sum = (rt->ls->sum + rt->rs->sum) % mod;}
inline void pushdown(node *rt) {
rt->ls->laz += rt->laz, rt->rs->laz += rt->laz;
rt->ls->sum += rt->ls->len * rt->laz, rt->rs->sum += rt->rs->len * rt->laz;
rt->ls->sum %= mod, rt->rs->sum %= mod, rt->laz = 0;
}
inline void build(node* &rt, int l, int r) {
if(!rt) alloc(rt);
rt->l = l, rt->r = r, rt->mid = (l + r) >> 1, rt->len = r - l + 1;
if(l == r) {rt->sum = wt[l] % mod; return;}
build(rt->ls, rt->l, rt->mid), build(rt->rs, rt->mid + 1, rt->r);
pushup(rt);
}
inline int query(node *rt, int l, int r) {
if(rt->l >= l && rt->r <= r) return rt->sum % mod;
if(rt->laz) pushdown(rt);
int ans = 0;
if(l <= rt->mid) ans += query(rt->ls, l, r);
if(r > rt->mid) ans += query(rt->rs, l, r);
return ans % mod;
}
inline void update(node *rt, int l, int r, int k) {
if(rt->l >= l && rt->r <= r) {rt->laz += k, rt->sum += rt->len * k; return;}
if(rt->laz) pushdown(rt);
if(l <= rt->mid) update(rt->ls, l, r, k);
if(r > rt->mid) update(rt->rs, l, r, k);
pushup(rt);
}
inline int Range(int x, int y, int k = 0) {
int ans = 0;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
if(k != 0) update(root, id[top[x]], id[x], k);
else ans = (ans + query(root, id[top[x]], id[x])) % mod; x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
if(k != 0) {update(root, id[x], id[y], k); return 0;}
return (ans + query(root, id[x], id[y])) % mod;
}
inline void dfs1(int x, int f, int deep) {
dep[x] = deep, fa[x] = f, siz[x] = 1;
for(Iter it = G[x].begin(); it != G[x].end(); ++it) {
if(*it == f) continue;
dfs1(*it, x, deep + 1);
siz[x] += siz[*it];
if(siz[*it] > siz[son[x]]) son[x] = *it;
}
}
inline void dfs2(int x, int topf) {
id[x] = ++cnt, wt[id[x]] = w[x], top[x] = topf;
if(!son[x]) return;
dfs2(son[x], topf);
for(Iter it = G[x].begin(); it != G[x].end(); ++it) {
if(*it == fa[x] || *it == son[x]) continue;
dfs2(*it, *it);
}
}
int main() {
read(n), read(m), read(r), read(mod);
for(int i = 1; i <= n; ++i) read(w[i]);
for(int i = 1; i < n; ++i) read(a), read(b), add(a, b), add(b, a);
dfs1(r, 0, 1), dfs2(r, r), build(root, 1, n);
while(m--) {
read(k), read(x);
if(k == 1) read(y), read(z), Range(x, y, z);
else if(k == 2) read(y), printf("%d\n", Range(x, y));
else if(k == 3) read(y), update(root, id[x], id[x] + siz[x] - 1, y);
else printf("%d\n", query(root, id[x], id[x] + siz[x] - 1));
}
return 0;
}
HLPP 最大流(cogs 14)
#include <list>
#include <cstdio>
#include <vector>
#include <algorithm>
const int MAXN = 10005; const int INF = 2147483647;
struct node {
int v, f, index;
node(int v, int f, int index) : v(v), f(f), index(index) {}
};
std::vector<node>edge[MAXN];
std::vector<int>list[MAXN], height, count, que, excess;
typedef std::list<int> List
std::vector<List::iterator>iter;
List dlist[MAXN];
int highest, highestActive;
typedef std::vector<node>::iterator Iterator;
inline void addEdge(const int u, const int v, const int f) {
edge[u].push_back(node(v, f, edge[v].size()));
edge[v].push_back(node(u, 0, edge[u].size() - 1));
}
inline void globalRelabel(int n, int t) {
height.assign(n, n); height[t] = 0; count.assign(n, 0);
que.clear(); que.resize(n + 1); int qh = 0, qt = 0;
for(que[qt++] = t; qh < qt;) {
int u = que[qh++], h = height[u] + 1;
for(Iterator p = edge[u].begin(); p != edge[u].end(); ++p)
if(height[p->v] == n && edge[p->v][p->index].f > 0)
count[height[p->v] = h]++, que[qt++] = p->v;
}
for(int i = 0; i <= n; i++) list[i].clear(), dlist[i].clear();
for(int u = 0; u < n; ++u)
if(height[u] < n) {
iter[u] = dlist[height[u]].insert(dlist[height[u]].begin(), u);
if(excess[u] > 0) list[height[u]].push_back(u);
}
highest = (highestActive = height[que[qt - 1]]);
}
inline void push(int u, node &e) {
int v = e.v, df = std::min(excess[u], e.f);
e.f -= df; edge[v][e.index].f += df; excess[u] -= df; excess[v] += df;
if(0 < excess[v] && excess[v] <= df) list[height[v]].push_back(v);
}
inline void discharge(int n, int u) {
int nh = n;
for(Iterator p = edge[u].begin(); p != edge[u].end; ++p) {
if(p->f > 0) {
if(height[u] == height[p->v] + 1) {
push(u, *p);
if(!excess[u]) return;
} else nh = std::min(nh, height[p->v] + 1);
}
}
int h = height[u];
if(cound[h] == 1) {
for(int i =h; i <= highest; ++i) {
for(List::iterator p = dlist[i].begin(); p != dlist[i].end(); ++p)
--count[height[*p]], height[*p] = n;
dlist[i].clear();
}
highest = h - 1;
} else {
--count[h], iter[u] = dlist[h].erase(iter[u]), height[u] = nh;
if(nh == n) return;
++count[nh], iter[u] = dlist[nh].insert(dlist[nh].begin(), u);
highest = std::max(highest, highestActive = nh), list[nh].push_back(u);
}
}
inline int hlpp(int n, int s, int t) {
if(s == t) return 0;
highestActive = highest = 0;
height.assign(n, 0), height[s] = n, iter.resize(n);
for(int i = 0; i < n; ++i) if(i != s)
iter[i] = dlist[height[i]].insert(dlist[height[i]].begin(), i);
count.assign(n, 0), count[0] = n - 1;
excess.assign(n, 0), excess[s] = INF, excess[t] = -INF;
for(int i = 0; i < (int)edge[s].size(); ++i) push(s, edge[s][i]);
globalRelabel(n, t);
for(int u; heightActive >= 0;) {
if(list[highestActive].empty()) {--heightActive; continue;}
u = list[highestActive].back(), list[highestActive].pop_back();
discharge(n, u);
}
return excess[t] + INF;
}
弄了个水题做做,LICS 吧。最长上升公共子序列。所以怎么做?其实就 n^2 求一个 LIS,然后判断一下加入的数是否是公共的就行了。
#include<cstdio>
#include<cstring>
using namespace std;
int n1, n2, T;
int a[505], b[505], f[505], temp;
int ans;
int max(int a, int b) {return a < b ? b : a;}
int main() {
#ifndef LOCAL
freopen("codes.in", "r", stdin);
freopen("codes.out", "w", stdout);
#endif
scanf("%d", &T);
while(T--) {
scanf("%d", &n1);
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for(int i = 1; i <= n1; i++) scanf("%d", &a[i]);
scanf("%d", &n2);
for(int i = 1; i <= n2; i++) scanf("%d", &b[i]);
memset(f, 0, sizeof(f));
ans = 0;
for(int i = 1;i <= n1; i++) {
temp = 0;
for (int j = 1;j <= n2; j++) {
if (a[i] > b[j]) temp = max(temp, f[j]);
else if(a[i] == b[j]) f[j]=max(f[j], temp+1);
ans = max(ans, f[j]);
}
}
printf("%d\n", ans);
}
return 0;
}
Splay 区间翻转(文艺平衡树)
#include <cstdio>
#include <algorithm>
using namespace std;
struct node {
node *ch[2]; int v, s, t;
node (int v = 0) : v(v), s(1), t(0) {ch[0] = ch[1] = NULL;}
} *root;
inline int size(node *o) {return o ? o->s : 0;}
inline void maintain(node *o) {o->s = 1 + size(o->ch[0]) + size(o->ch[1]);}
inline void pushdown(node *o) {
if(o->t) {
swap(o->ch[0], o->ch[1]);
if(o->ch[0]) o->ch[0]->t ^= 1;
if(o->ch[1]) o->ch[1]->t ^= 1;
o->t = 0;
}
}
inline void rotate(node *&o, int t) {
node *u = o->ch[t]; pushdown(u);
o->ch[t] = u->ch[t ^ 1], u->ch[t ^ 1] = o; maintain(o), maintain(u), o = u;
}
inline void insert(node *&o, int v) {
if(!o) o = new node(v);
else insert(o->ch[v < o->v ? 0 : 1], v), maintain(o);
}
inline void splay(node *&o, int k) {
pushdown(o);
int l = size(o->ch[0]);
if(l + 1 == k) return;
int d = k <= l ? 0 : 1, k2 = d ? k - l - 1 : k;
node *&c = o->ch[d]; pushdown(c);
int l2 = size(c->ch[0]);
if(l2 + 1 != k2) {
int d2 = k2 <= l2 ? 0 : 1;
splay(c->ch[d2], d2 ? k2 - l2 - 1 : k2);
if(d == d2) rotate(o, d);
else rotate(c, d2);
}
rotate(o, d);
}
int kth(node* &o, int k) {splay(o, k); return o->v;}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) insert(root, i), splay(root, i);
for(int i = 1; i <= m; ++i) {
int l, r;
scanf("%d%d", &l, &r);
if(l == 1 && r == n) root->t ^= 1;
else if(l == 1) splay(root, r + 1), root->ch[0]->t ^= 1;
else if(r == n) splay(root, l - 1), root->ch[1]->t ^= 1;
else splay(root, l - 1), splay(root->ch[1], r - size(root->ch[0])),
root->ch[1]->ch[0]->t ^= 1;
}
for(int i = 1; i <= n; ++i) printf("%d%c", kth(root, i), i == n ? '\n' : ' ');
return 0;
}