From 299b05c265387b72679ad836de910a80eee75f5a Mon Sep 17 00:00:00 2001 From: Kirito <1362050620@qq.com> Date: Tue, 22 Nov 2016 09:38:35 +0800 Subject: [PATCH] Add files via upload --- .ACM-Templates/TXTs/分数.txt | 27 + .ACM-Templates/TXTs/图论模板.txt | 2263 ++++++++++++++++++++++++++ .ACM-Templates/TXTs/基础模板.txt | 1008 ++++++++++++ .ACM-Templates/TXTs/字符串.txt | 401 +++++ .ACM-Templates/TXTs/并查集.txt | 21 + .ACM-Templates/TXTs/应用.txt | 210 +++ .ACM-Templates/TXTs/排序查找.txt | 41 + .ACM-Templates/TXTs/数学数论.txt | 634 ++++++++ .ACM-Templates/TXTs/数据结构.txt | 2209 +++++++++++++++++++++++++ .ACM-Templates/TXTs/数据结构模板.txt | 456 ++++++ .ACM-Templates/TXTs/数论模板.txt | 825 ++++++++++ .ACM-Templates/TXTs/日期.txt | 47 + .ACM-Templates/TXTs/混合模板.txt | 772 +++++++++ .ACM-Templates/TXTs/矩阵.txt | 131 ++ .ACM-Templates/TXTs/稀疏表.txt | 41 + .ACM-Templates/TXTs/组合数学.txt | 183 +++ .ACM-Templates/TXTs/莫队.txt | 28 + .ACM-Templates/TXTs/计算几何.txt | 1393 ++++++++++++++++ .ACM-Templates/TXTs/输入输出.txt | 71 + .ACM-Templates/TXTs/高精度.txt | 195 +++ 20 files changed, 10956 insertions(+) create mode 100644 .ACM-Templates/TXTs/分数.txt create mode 100644 .ACM-Templates/TXTs/图论模板.txt create mode 100644 .ACM-Templates/TXTs/基础模板.txt create mode 100644 .ACM-Templates/TXTs/字符串.txt create mode 100644 .ACM-Templates/TXTs/并查集.txt create mode 100644 .ACM-Templates/TXTs/应用.txt create mode 100644 .ACM-Templates/TXTs/排序查找.txt create mode 100644 .ACM-Templates/TXTs/数学数论.txt create mode 100644 .ACM-Templates/TXTs/数据结构.txt create mode 100644 .ACM-Templates/TXTs/数据结构模板.txt create mode 100644 .ACM-Templates/TXTs/数论模板.txt create mode 100644 .ACM-Templates/TXTs/日期.txt create mode 100644 .ACM-Templates/TXTs/混合模板.txt create mode 100644 .ACM-Templates/TXTs/矩阵.txt create mode 100644 .ACM-Templates/TXTs/稀疏表.txt create mode 100644 .ACM-Templates/TXTs/组合数学.txt create mode 100644 .ACM-Templates/TXTs/莫队.txt create mode 100644 .ACM-Templates/TXTs/计算几何.txt create mode 100644 .ACM-Templates/TXTs/输入输出.txt create mode 100644 .ACM-Templates/TXTs/高精度.txt diff --git a/.ACM-Templates/TXTs/分数.txt b/.ACM-Templates/TXTs/分数.txt new file mode 100644 index 0000000..2302951 --- /dev/null +++ b/.ACM-Templates/TXTs/分数.txt @@ -0,0 +1,27 @@ +// +struct Frac { + ll a, b; //, ĸ + Frac(const ll &_a = 0, const ll &_b = 1): a(_a), b(_b) { + if (b < 0) { a = -a; b = -b; } + ll t = __gcd(a, b); a /= t, b /= t; + } + Frac operator-()const { return Frac(-a, b); } + Frac operator+(const Frac &r)const { return Frac(a * r.b + r.a * b, b * r.b); } + Frac operator-(const Frac &r)const { return Frac(a * r.b - r.a * b, b * r.b); } + Frac operator*(const Frac &r)const { return Frac(a * r.a, b * r.b); } + Frac operator/(const Frac &r)const { return Frac(a * r.b, b * r.a); } + Frac &operator+=(const Frac &r) { return *this = *this + r; } + Frac &operator-=(const Frac &r) { return *this = *this - r; } + Frac &operator*=(const Frac &r) { return *this = *this * r; } + Frac &operator/=(const Frac &r) { return *this = *this / r; } + bool operator<(const Frac &r)const { return a * r.b < r.a * b; } + bool operator>(const Frac &r)const { return a * r.b > r.a * b; } + bool operator==(const Frac &r)const { return a * r.b == r.a * b; } + bool operator!=(const Frac &r)const { return a * r.b != r.a * b; } + bool operator<=(const Frac &r)const { return a * r.b <= r.a * b; } + bool operator>=(const Frac &r)const { return a * r.b >= r.a * b; } + void print() { if (b == 1) { printf("%I64d", a); } else { printf("%I64d/%I64d", a, b); } } + friend ostream &operator<<(ostream &out, const Frac &r) { + if (r.b == 1) { out << r.a; } else { out << r.a << '/' << r.b; } return out; + } +}; diff --git a/.ACM-Templates/TXTs/图论模板.txt b/.ACM-Templates/TXTs/图论模板.txt new file mode 100644 index 0000000..df86d39 --- /dev/null +++ b/.ACM-Templates/TXTs/图论模板.txt @@ -0,0 +1,2263 @@ +==========ͼģ LCA========= +//LCA (Least Common Ancestors, ) +//dfs + ST O(nlogn + q) +int dfso[N << 1], cnt; //ŷ, dfs, Ϊ2n-1, ±1ʼ +int pos[N]; //pos[i]ʾiŷеһγֵλ +int dep[N << 1]; //ŷжӦ +int p[N << 1] = { -1}, dp[N << 1][20]; +void initRMQ(int n) { + for (int i = 1; i <= n; i++) { p[i] = p[i - 1] + !(i & (i - 1)); dp[i][0] = i; } + for (int j = 1; j <= p[n]; j++) { + for (int i = 1; i + (1 << j) - 1 <= n; i++) { + dp[i][j] = dep[dp[i][j - 1]] < dep[dp[i + (1 << (j - 1))][j - 1]] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1]; + } + } +} +inline int queryRMQ(int l, int r) { + if (l > r) { swap(l, r); } + int k = p[r - l + 1]; + return dep[dp[l][k]] <= dep[dp[r - (1 << k) + 1][k]] ? dp[l][k] : dp[r - (1 << k) + 1][k]; +} +void dfs(int u, int p, int d) { + dfso[++cnt] = u; dep[cnt] = d; pos[u] = cnt; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (v != p) { dfs(v, u, d + 1); dfso[++cnt] = u; dep[cnt] = d; } + } +} +void initLCA(int rt, int n) { + cnt = 0; dfs(rt, rt, 0); initRMQ(2 * n - 1); +} +inline int queryLCA(int u, int v) { //ѯuvLCA + return dfso[queryRMQ(pos[u], pos[v])]; +} +// O(nlogn + qlogn) +const int DEP = 20; +int fa[N][DEP]; //fa[i][j]ʾiĵ2^j +int dep[N]; // +void bfs(int rt) { + queue que; que.push(rt); + dep[rt] = 0; fa[rt][0] = rt; + while (!que.empty()) { + int u = que.front(); que.pop(); + for (int i = 1; i < DEP; i++) { fa[u][i] = fa[fa[u][i - 1]][i - 1]; } + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (v != fa[u][0]) { dep[v] = dep[u] + 1; fa[v][0] = u; que.push(v); } + } + } +} +int queryLCA(int u, int v) { + if (dep[u] > dep[v]) { swap(u, v); } + for (int d = dep[v] - dep[u], i = 0; d; d >>= 1, i++) { + if (d & 1) { v = fa[v][i]; } + } + if (u == v) { return u; } + for (int i = DEP - 1; i >= 0; i--) { + if (fa[u][i] != fa[v][i]) { u = fa[u][i]; v = fa[v][i]; } + } + return fa[u][0]; +} +//Tarjan O(n + q) +int n, fa[N], ancestor[N], ans[N]; +bool vis[N]; +int qhead[N], qto[M], qnxt[M], qtot; +void init() { + qtot = 0; memset(qhead, -1, sizeof(qhead)); + memset(ancestor, 0, sizeof(ancestor)); memset(vis, 0, sizeof(vis)); + for (int i = 0; i <= n; i++) { fa[i] = i; } +} +void qaddedge(int x, int y) { + qto[qtot] = y; qnxt[qtot] = qhead[x]; qhead[x] = qtot++; + qto[qtot] = x; qnxt[qtot] = qhead[y]; qhead[y] = qtot++; +} +int findfa(int n) { return n == fa[n] ? n : fa[n] = findfa(fa[n]); } +inline void unite(int x, int y) { + x = findfa(x); y = findfa(y); + if (x != y) { fa[y] = x; } +} +void Tarjan_LCA(int u) { + ancestor[u] = u; vis[u] = true; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (!vis[v]) { Tarjan_LCA(v); unite(u, v); ancestor[findfa(u)] = u; } + } + for (int i = qhead[u]; ~i; i = qnxt[i]) { + int v = qto[i]; + if (vis[v]) { ans[i >> 1] = ancestor[findfa(v)]; } + } +} + +==================ͼ-ͨ================== +//ͼĸ㡢˫ͨ +//[ͨͨ] +//һͨͼ, һ㼯, ɾ㼯, +//ԼжıԺ, ԭͼɶͨ, ͳ㼯Ϊ㼯 +//һͼĵͨȵĶΪ, С㼯еĶ +//Ƶ, һ߼, ɾ߼Ժ, ԭͼɶͨ, ͳ㼯Ϊ߼ +//һͼıͨȵĶΪ, С߼еı +//[˫ͨͼ] +//һͨͼĵͨȴ1, Ƹͼǵ˫ͨ(point biconnected), ˫ͨͨ +//һͼи, ҽͼĵͨΪ1, 㼯ϵΨһԪرΪ(cut point), ֽйؽڵ(articulation point) +//һͨͼıͨȴ1, ƸͼDZ˫ͨ(edge biconnected), ˫ͨͨ +//һͼ, ҽͼıͨΪ1, ߼ϵΨһԪرΪ(bridge), ֽйؽڱ(articulation edge) +//Կ, ˫ͨ˫ͨԼΪ˫ͨ, ֮ijϵ, ᵽ˫ͨ, ȿָ˫ͨ, ָֿ˫ͨ +//[˫ͨ] +//ͼGͼG', G'˫ͨ, G'Ϊ˫ͨͼ +//һ˫ͨͼG'κһ˫ͨͼӼ, G'Ϊ˫ͨͼ +//˫ͨ(biconnected component), ͨ, ͼļ˫ͨͼ, ˫ֽͨ +//[] +//ͼ, DFS(u)Ϊu(¼Ϊ)бĴ +//Low(u)ΪuuͨǸӱ׷ݵĽڵ, DFSСĽڵ +//ݶ, : Low(u) = Min {DFS(u) DFS(v) (u,v)Ϊ() ȼDFS(v) < DFS(u)vΪuĸ׽ڵLow(v) (u,v)Ϊ֦(ӱ)} +//һuǸ, ҽ(1)(2) +//(1)uΪ, uжһ +//(2)uΪ, (u,v)Ϊ֦(Ƹӱ, uΪvеĸ), ʹDFS(u)<=Low(v) +//һ(u,v), ҽ(u,v)Ϊ֦, DFS(u) e[N], re[N], pos; +bool vis[N]; +int belong[N], num[N], scc, cnt; //, , +void dfs(int u) { + vis[u] = true; + for (int i = 0; i < (int)e[u].size(); i++) { + if (!vis[e[u][i]]) { dfs(e[u][i]); } + } + pos.push_back(u); +} +void rdfs(int u, int k) { + vis[u] = true; belong[u] = k; cnt++; + for (int i = 0; i < (int)re[u].size(); i++) { + if (!vis[re[u][i]]) { rdfs(re[u][i], k); } + } +} +void SCC(int n) { + memset(vis, 0, sizeof(vis)); pos.clear(); + for (int i = 0; i < n; i++) { if (!vis[i]) { dfs(i); } } + memset(vis, 0, sizeof(vis)); memset(num, 0, sizeof(num)); scc = 0; + for (int i = (int)pos.size() - 1; i >= 0; i--) { + if (!vis[pos[i]]) { cnt = 0; rdfs(pos[i], ++scc); num[scc] = cnt; } + } +} +//Tarjan㷨 O(V + E) +vector e[N]; +int low[N], dfn[N], index, belong[N], num[N], scc; //, , +stack stk; +bool instack[N]; +void Tarjan(int u) { + int v; low[u] = dfn[u] = ++index; stk.push(u); instack[u] = true; + for (int i = 0; i < (int)e[u].size(); i++) { + int v = e[u][i]; + if (!dfn[v]) { Tarjan(v); low[u] = min(low[u], low[v]); } + else if (instack[v] && low[u] > dfn[v]) { low[u] = dfn[v]; } + } + if (low[u] == dfn[u]) { + scc++; + do { + v = stk.top(); stk.pop(); + instack[v] = false; belong[v] = scc; num[scc]++; + } while (v != u); + } +} +void SCC(int n) { + memset(dfn, 0, sizeof(dfn)); memset(num, 0, sizeof(num)); + memset(instack, 0, sizeof(instack)); index = scc = 0; + while (!stk.empty()) { stk.pop(); } + for (int i = 0; i < n; i++) { if (!dfn[i]) { Tarjan(i); } } +} +//ͼĸ +//Tarjan㷨 O(V + E) +int low[N], dfn[N], index, addblock[N], bridge; +bool instack[N], cut[N], ecut[M]; +stack stk; +void Tarjan(int u, int p) { + int son = 0; low[u] = dfn[u] = ++index; + stk.push(u); instack[u] = true; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (v == p) { continue; } + if (!dfn[v]) { + Tarjan(v, u); son++; + low[u] = min(low[u], low[v]); + if (u != p && low[v] >= dfn[u]) { // + cut[u] = true; addblock[u]++; + } + if (low[v] > dfn[u]) { // + bridge++; ecut[i] = ecut[i ^ 1] = true; + } + } else if (low[u] > dfn[v]) { low[u] = dfn[v]; } + } + if (u == p && son > 1) { cut[u] = true; } + if (u == p) { addblock[u] = son - 1; } + instack[u] = false; stk.pop(); +} +void CUT(int n) { + memset(dfn, 0, sizeof(dfn)); memset(addblock, 0, sizeof(addblock)); + memset(instack, 0, sizeof(instack)); memset(cut, 0, sizeof(cut)); memset(ecut, 0, sizeof(ecut)); + while (!stk.empty()) { stk.pop(); } index = bridge = 0; + for (int i = 0; i < n; i++) { if (!dfn[i]) { Tarjan(i, i); } } +} +//ͼı˫ͨ +//еԺ, űɾ, ԭͼ˶ͨ, ÿͨһ˫ͨ +//Ųκһ˫ͨ, ıߺÿ㶼ֻһ˫ͨ +//Tarjan㷨 O(V + E) +int low[N], dfn[N], index, belong[N], bridge, block; +bool instack[N], ecut[M]; +stack stk; +void Tarjan(int u, int p) { + low[u] = dfn[u] = ++index; stk.push(u); instack[u] = true; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (v == p) { continue; } + if (!dfn[v]) { + Tarjan(v, u); + low[u] = min(low[u], low[v]); + if (low[v] > dfn[u]) { // + bridge++; ecut[i] = ecut[i ^ 1] = true; + } + } else if (low[u] > dfn[v]) { low[u] = dfn[v]; } + } + if (low[u] == dfn[u]) { + int v; block++; + do { + v = stk.top(); stk.pop(); instack[v] = false; belong[v] = block; + } while (u != v); + } +} +void EBCC(int n) { + memset(dfn, 0, sizeof(dfn)); memset(instack, 0, sizeof(instack)); memset(cut, 0, sizeof(cut)); + while (!stk.empty()) { stk.pop(); } index = bridge = block = 0; + for (int i = 0; i < n; i++) { if (!dfn[i]) { Tarjan(i, -1); } } +} +//ͼĵ˫ͨ +//ڵ˫ͨ, ʵĹо˳ÿ˫ͨ +//һջ, 洢ǰ˫ͨ, ͼʱ, ÿҵһ֦߻(Ǻ), Ͱ߼ջ +//ijʱDFS(u)<=Low(v), ˵uһ, ͬʱѱߴջһȡ, +//ֱ˱(u,v), ȡЩĵ, һ˫ͨ +//ڶ˫ͨ, ÿֻһ˫ͨ +//Tarjan㷨 O(V + E) +int low[N], dfn[N], index, belong[N], block; //, , +stack stk; +bool instack[N]; +void Tarjan(int u, int p) { + low[u] = dfn[u] = ++index; + stk.push(u); instack[u] = true; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (v == p) { continue; } + if (!dfn[v]) { + Tarjan(v, u); + low[u] = min(low[u], low[v]); + if (low[v] >= dfn[u]) { //uΪ + int vv; block++; + do { + vv = stk.top(); stk.pop(); instack[vv] = false; + belong[vv] = block; + } while (vv != v); + } + } else if (instack[v] && low[u] > dfn[v]) { low[u] = dfn[v]; } + } +} +void BCC(int n) { + memset(dfn, 0, sizeof(dfn)); memset(instack, 0, sizeof(instack)); + while (!stk.empty()) { stk.pop(); } index = block = 0; + for (int i = 0; i < n; i++) { if (!dfn[i]) { Tarjan(i, -1); } } +} +//˫ͨͼ +//Ϊе, ȻɾЩű, ʣµÿͨ鶼һ˫ͨͼ +//ÿ˫ͨͼΪһ, ٰű߼ӻ, ͼһһ, ͨΪ1 +//ͳƳжΪ1Ľڵĸ, ΪҶڵĸ, Ϊleaf +//(leaf + 1) / 2, ʹﵽ߶ͨ, ӵı(leaf + 1) / 2 +//巽Ϊ, ȰԶҶڵ֮һ, ԰㵽ȵ·еһ, +//ΪһγɵĻһ˫ͨġȻԶҶڵ, һһ, ǡ(leaf + 1) / 2, еһ + + +=============================ͼ-ƥ============================ +//ͼ۵㡢߼Ͷͼظ +//㸲: 㸲Ǽһ㼯, ʹбһ˵ڼ +//߸: ߸Ǽһ߼, ʹе㶼뼯ıڽ +//: һ㼯, 㲻, VΪ +//: żһ㼯, +//߶: ߶һ߼, ߼е߲ڽ +//֧伯: ֧伯һ㼯, ʹһڵڼ +//֧伯: ֧伯һ߼, ʹбһڽӱڼ +//С·: þٵIJཻ·޻ͼGж, ÿϸһ·, ·ijȿΪ0() +//ƥ: ƥһ߼, ߼еıڽ +//ƥеĵΪƥ򱥺͵㣻֮, Ϊδƥδ͵ +//(alternating path): ͼһ·, ڵ, һƥ, һƥ +//(augmenting path): һʼյ㶼ΪδƥĽ +//ƥ(maximum matching): ߵƥ +//ƥ(matching number): ƥĴС +//ƥ(perfect matching): ƥеƥ +//걸ƥ(complete matching): ƥ˶ͼСϣͼX, YСǸеƥ +//춨: һƥƥ䵱ҽû +//ƥ㷨ǻ춨: һƥƥ䵱ҽû +//ƥ = С = ƥ + ұδƥ +//С߸ = ͼеĸ - ƥ = + +//ͼƥ +//Hungary + dfs +//ڽӾ O(V^2) +int uN, vN, match[N]; //ҵĿ +bool g[N][N], check[N]; +bool dfs(int u) { + for (int v = 0; v < vN; v++) { + if (g[u][v] && !check[v]) { + check[v] = true; + if (match[v] == -1 || dfs(match[v])) { + match[v] = u; match[u] = v; return true; + } + } + } + return false; +} +//ڽӱ O(V*E) +int head[N], to[M], nxt[M], tot, uN, match[N]; +bool check[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } +bool dfs(int u) { + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (!check[v]) { + check[v] = true; + if (match[v] == -1 || dfs(match[v])) { + match[v] = u; match[u] = v; return true; + } + } + } + return false; +} +int Hungary() { + memset(match, -1, sizeof(match)); + int res = 0; + for (int u = 0; u < uN; u++) { + if (match[u] == -1) { + memset(check, 0, sizeof(check)); + if (dfs(u)) { res++; } + } + } + return res; +} +//Hungary + bfs + ڽӾ O(V*E) +bool g[N][N]; +int uN, vN, match[N], check[N], pre[N]; +int Hungary() { + memset(match, -1, sizeof(match)); + memset(check, -1, sizeof(check)); + queue que; + int res = 0; + for (int i = 0; i < uN; i++) { + if (match[i] == -1) { + while (!que.empty()) { que.pop(); } + que.push(i); pre[i] = -1; + bool flag = false; + while (!que.empty() && !flag) { + int u = que.front(); que.pop(); + for (int v = 0; v < vN && !flag; v++) { + if (g[u][v] && check[v] != i) { + check[v] = i; que.push(match[v]); + if (~match[v]) { pre[match[v]] = u; } + else { + flag = true; + for (int a = u, b = v; ~a;) { + int t = match[a]; match[a] = b; match[b] = a; a = pre[a]; b = t; + } + } + } + } + } + if (~match[i]) { res++; } + } + } + return res; +} +//Hungary + bfs + ڽӱ O(V*E) +int head[N], to[M], nxt[M], tot, uN, match[N], check[N], pre[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } +int Hungary() { + memset(match, -1, sizeof(match)); + memset(check, -1, sizeof(check)); + queue que; + int res = 0; + for (int i = 0; i < uN; i++) { + if (match[i] == -1) { + while (!que.empty()) { que.pop(); } + que.push(i); pre[i] = -1; + bool flag = false; + while (!que.empty() && !flag) { + int u = que.front(); que.pop(); + for (int i = head[u]; ~i && !flag; i = nxt[i]) { + int v = to[i]; + if (check[v] != i) { + check[v] = i; que.push(match[v]); + if (~match[v]) { pre[match[v]] = u; } + else { + flag = true; + for (int a = u, b = v; ~a;) { + int t = match[a]; match[a] = b; match[b] = a; a = pre[a]; b = t; + } + } + } + } + } + if (~match[i]) { res++; } + } + } + return res; +} +//Hopcroft-Karp + vector + O(sqrt(V)*E) +const int INF = 0x3f3f3f3f; +vector g[N]; +int uN, matchx[N], matchy[N], dx[N], dy[N], dis; +bool check[N]; +bool SearchP() { + memset(dx, -1, sizeof(dx)); + memset(dy, -1, sizeof(dy)); + queue que; dis = INF; + for (int i = 0; i < uN; i++) { if (matchx[i] == -1) { dx[i] = 0; que.push(i); } } + while (!que.empty()) { + int u = que.front(); que.pop(); + if (dx[u] > dis) { break; } + for (size_t i = 0; i < g[u].size(); i++) { + int v = g[u][i]; + if (dy[v] == -1) { + dy[v] = dx[u] + 1; + if (matchy[v] == -1) { dis = dy[v]; } + else { dx[matchy[v]] = dy[v] + 1; que.push(matchy[v]); } + } + } + } + return dis != INF; +} +bool dfs(int u) { + for (size_t i = 0; i < g[u].size(); i++) { + int v = g[u][i]; + if (!check[v] && dy[v] == dx[u] + 1) { + check[v] = true; + if (~matchy[v] && dy[v] == dis) { continue; } + if (matchy[v] == -1 || dfs(matchy[v])) { + matchy[v] = u; matchx[u] = v; return true; + } + } + } + return false; +} +int HK() { + memset(matchx, -1, sizeof(matchx)); + memset(matchy, -1, sizeof(matchy)); + int res = 0; + while (SearchP()) { + memset(check, 0, sizeof(check)); + for (int i = 0; i < uN; i++) { + if (matchx[i] == -1 && dfs(i)) { res++; } + } + } + return res; +} +//ͼƥ +//Kuhn-Munkers + ڽӾ O(uN^2*vN) +//СȨƥ,ɽȨֵȡ෴,ȡ෴ ıŴ0ʼ +const int INF = 0x3f3f3f3f; +int uN, vN, g[N][N]; +int matchy[N], lx[N], ly[N]; //yиƥ״̬, ж +int slack[N]; //ɳ +bool visx[N], visy[N]; +bool dfs(int u) { + visx[u] = true; + for (int v = 0; v < vN; v++) { + if (visy[v]) { continue; } + int tmp = lx[u] + ly[v] - g[u][v]; + if (tmp == 0) { + visy[v] = true; + if (matchy[v] == -1 || dfs(matchy[v])) { matchy[v] = u; return true; } + } else if (slack[v] > tmp) { slack[v] = tmp; } + } + return false; +} +int KM() { + memset(matchy, -1, sizeof(matchy)); + memset(ly, 0, sizeof(ly)); + for (int i = 0; i < uN; i++) { lx[i] = *max_element(g[i], g[i] + vN); } + for (int u = 0; u < uN; u++) { + memset(slack, 0x3f, sizeof(slack)); + for (;;) { + memset(visx, 0, sizeof(visx)); + memset(visy, 0, sizeof(visy)); + if (dfs(u)) { break; } + int d = INF; + for (int i = 0; i < vN; i++) { if (!visy[i] && d > slack[i]) { d = slack[i]; } } + for (int i = 0; i < uN; i++) { if (visx[i]) { lx[i] -= d; } } + for (int i = 0; i < vN; i++) { if (visy[i]) { ly[i] += d; } else { slack[i] -= d; } } + } + } + int res = 0; + for (int i = 0; i < vN; i++) { if (matchy[i] != -1) { res += g[matchy[i]][i]; } } + return res; +} +//ͼƥ +int uN, vN, g[N][N], match[N][N]; //match[i][0]Ϊ +int num[N]; //ұƥ +bool check[N]; +bool dfs(int u) { + for (int v = 0; v < vN; v++) { + if (g[u][v] && !check[v]) { + check[v] = true; + if (match[v][0] < num[v]) { match[v][++match[v][0]] = u; return true; } + for (int i = 1; i <= num[0]; i++) { + if (dfs(match[v][i])) { match[v][i] = u; return true; } + } + } + } + return false; +} +int Hungary() { + int res = 0; + for (int i = 0; i < vN; i++) { match[i][0] = 0; } + for (int u = 0; u < uN; u++) { + memset(check, false, sizeof(check)); + res += dfs(u); + } + return res; +} +//һͼƥ +//ڽӾ O(V^3) +int n, match[N]; +bool g[N][N], check[N]; +bool aug(int now) { + bool ret = false; check[now] = true; + for (int i = 0; i < n; i++) { + if (!check[i] && g[now][i]) { + if (match[i] == -1) { match[now] = i; match[i] = now; ret = true; } + else { + check[i] = true; + if (aug(match[i])) { match[now] = i, match[i] = now, ret = true; } + check[i] = false; + } + if (ret) { break; } + } + } + check[now] = false; return ret; +} +//ڽӱ O(V*E) +int head[N], to[M], nxt[M], tot, match[N]; +bool check[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } +bool aug(int now) { + bool ret = false; check[now] = true; + for (int i = head[now]; ~i; i = nxt[i]) { + int v = to[i]; + if (!check[v]) { + if (match[v] == -1) { match[now] = v; match[v] = now; ret = true; } + else { + check[v] = true; + if (aug(match[v])) { match[now] = v; match[v] = now; ret = true; } + check[v] = false; + } + if (ret) { break; } + } + } + check[now] = false; return ret; +} +int graphMatch() { + memset(match, -1, sizeof(match)); + memset(check, 0, sizeof(check)); + for (int i = 0, j = n; i < n && j >= 2; i++) { + if (match[i] == -1 && aug(i)) { i = -1, j -= 2; } + } + int ret = 0; + for (int i = 0; i < n; i++) { ret += (match[i] != -1); } + return ret >> 1; +} +// + vector O(V^3) ıŴ0ʼ +int n, match[N], fa[N], nxt[N], mark[N], vis[N], t; +vector e[N]; queue que; +int findfa(int n) { return n == fa[n] ? n : fa[n] = findfa(fa[n]); } +void unite(int x, int y) { fa[findfa(x)] = findfa(y); } +int lca(int x, int y) { + for (t++;; swap(x, y)) { + if (x == -1) { continue; } + if (vis[x = findfa(x)] == t) { return x; } + vis[x] = t; x = match[x] == -1 ? -1 : nxt[match[x]]; + } +} +void group(int a, int p) { + for (int b, c; a != p; unite(a, b), unite(b, c), a = c) { + b = match[a]; c = nxt[b]; + if (findfa(c) != p) { nxt[c] = b; } + if (mark[b] == 2) { mark[b] = 1; que.push(b); } + if (mark[c] == 2) { mark[c] = 1; que.push(c); } + } +} +void aug(int st) { + for (int i = 0; i < n; i++) { fa[i] = i; } + memset(nxt, -1, sizeof(nxt)); memset(vis, -1, sizeof(vis)); memset(mark, 0, sizeof(mark)); + while (!que.empty()) { que.pop(); } que.push(st); mark[st] = 1; + while (match[st] == -1 && !que.empty()) { + int u = que.front(); que.pop(); + for (int i = 0; i < (int)e[u].size(); i++) { + int v = e[u][i]; + if (v == match[u] || findfa(u) == findfa(v) || mark[v] == 2) { continue; } + if (mark[v] == 1) { + int p = lca(u, v); + if (findfa(u) != p) { nxt[u] = v; } + if (findfa(v) != p) { nxt[v] = u; } + group(u, p); group(v, p); + } else if (match[v] == -1) { + nxt[v] = u; + for (int j = v, k, l; ~j; j = l) { k = nxt[j]; l = match[k]; match[j] = k; match[k] = j; } + break; + } else { nxt[v] = u; que.push(match[v]); mark[match[v]] = 1; mark[v] = 2; } + } + } +} +int solve(int n) { + memset(match, -1, sizeof(match)); t = 0; int ret = 0; + for (int i = 0; i < n; i++) { if (match[i] == -1) { aug(i); } } + for (int i = 0; i < n; i++) { ret += (match[i] > i); } + return ret; +} +//ural 1099 +int main() { + int u, v; + scanf("%d", &n); + while (~scanf("%d%d", &u, &v)) { e[--u].push_back(--v); e[v].push_back(u); } + int ans = solve(n); + printf("%d\n", ans * 2); + for (int u = 0; u < n; u++) { + if (u < match[u]) { printf("%d %d\n", u + 1, match[u] + 1); } + } +} + +============ͼ-========== +//С +//Prim + ڽӾ O(V^2) +typedef int wtype; +const wtype INF = 0x3f3f3f3f; +int n; wtype mp[N][N], cost[N]; +bool vis[N]; +wtype Prim(int src) { + memset(vis, 0, sizeof(vis)); memcpy(cost, mp[src], sizeof(mp[src])); + wtype ret = 0; vis[src] = true; + for (int j = 1; j < n; j++) { + int u = -1; wtype mn = INF; + for (int i = 0; i < n; i++) { + if (!vis[i] && mn > cost[i]) { mn = cost[i]; u = i; } + } + if (mn == INF) { return -1; } //ԭͼͨ + vis[u] = true; ret += mn; + for (int v = 0; v < n; v++) { + if (!vis[v] && cost[v] > mp[u][v]) { cost[v] = mp[u][v]; } + } + } + return ret; +} +//Prim + priority_queue + ڽӱ O(ElogV) +typedef int wtype; +int head[N], to[M], nxt[M], tot; wtype len[M], cost[N]; +bool vis[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y, wtype z) { to[tot] = y; len[tot] = z; nxt[tot] = head[x]; head[x] = tot++; } +struct Node { + int v; wtype w; + bool operator<(const Node &r)const { return w > r.w; } +}; +wtype Prim(int src) { + memset(cost, 0x3f, sizeof(cost)); memset(vis, 0, sizeof(vis)); + wtype ret = 0; + priority_queue que; que.push((Node) {src, cost[src] = 0}); + while (!que.empty()) { + int u = que.top().v; que.pop(); + if (vis[u]) { continue; } + vis[u] = true; ret += cost[u]; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (!vis[v] && cost[v] > len[i]) { cost[v] = len[i]; que.push((Node) {v, cost[v]}); } + } + } + return ret; +} +//Kruskal + ڽӱ O(ElogE) +typedef int wtype; +struct Edge { + int u, v; wtype w; + bool operator<(const Edge &r)const { return w < r.w; } +} edge[M]; +int n, fa[N], tot; //ӱǰֵΪ0 +void addedge(int u, int v, wtype w) { edge[tot].u = u; edge[tot].v = v; edge[tot++].w = w; } +int findfa(int x) { return fa[x] == -1 ? x : fa[x] = findfa(fa[x]); } +wtype Kruskal() { + memset(fa, -1, sizeof(fa)); + sort(edge, edge + tot); + int cnt = 0; wtype ret = 0; + for (int i = 0; i < tot; i++) { + int u = edge[i].u, v = edge[i].v, t1 = findfa(u), t2 = findfa(v); wtype w = edge[i].w; + if (t1 != t2) { ret += w; fa[t1] = t2; cnt++; } + if (cnt == n - 1) { break; } + } + if (cnt < n - 1) { return -1; } //ͨ + return ret; +} +//С +//Prim + ڽӾ O(V^2 + E) +//Сʱ, Mx[i][j]ʾMSTijȨ +//, ֱöвMSTеı, 滻Ȩı, ´ +typedef int wtype; +const wtype INF = 0x3f3f3f3f; +int n, pre[N]; +wtype mp[N][N], cost[N], Mx[N][N]; //Mx[i][j]ʾСдij·еȨ +bool vis[N], used[N][N]; +wtype Prim() { + memset(Mx, 0, sizeof(Mx)); + memset(pre, 0, sizeof(pre)); + memset(vis, 0, sizeof(vis)); + memset(used, 0, sizeof(used)); + wtype ret = 0; vis[0] = true; pre[0] = -1; + for (int i = 1; i < n; i++) { cost[i] = mp[0][i]; } + for (int j = 1; j < n; j++) { + int u = -1; wtype mn = INF; + for (int j = 0; j < n; j++) + if (!vis[j] && mn > cost[j]) { mn = cost[j]; u = j; } + if (mn == INF) { return -1; } //ԭͼͨ + vis[u] = true; ret += mn; + used[u][pre[u]] = used[pre[u]][u] = true; + for (int v = 0; v < n; v++) { + if (vis[v]) { Mx[v][u] = Mx[u][v] = max(Mx[v][pre[u]], cost[u]); } + if (!vis[v] && cost[v] > mp[u][v]) { cost[v] = mp[u][v]; pre[v] = u; } + } + } + return ret; +} +//Kruskal + ڽӱ O(VElogE) +typedef int wtype; +const wtype INF = 0x3f3f3f3f; +struct Edge { + int u, v; wtype w; + bool operator<(const Edge &r)const { return w < r.w; } +} edge[M]; +int n, fa[N], path[N], tot; //ӱǰֵΪ0 +void addedge(int u, int v, wtype w) { edge[tot].u = u; edge[tot].v = v; edge[tot++].w = w; } +int findfa(int x) { return fa[x] == -1 ? x : fa[x] = findfa(fa[x]); } +wtype Kruskal() { + memset(fa, -1, sizeof(fa)); + sort(edge, edge + tot); + int cnt = 0; wtype ret = 0; + for (int i = 0; i < tot; i++) { + int u = edge[i].u, v = edge[i].v, t1 = findfa(u), t2 = findfa(v); wtype w = edge[i].w; + if (t1 != t2) { ret += w; fa[t1] = t2; path[cnt++] = i; } + if (cnt == n - 1) { break; } + } + if (cnt < n - 1) { return -1; } //ͨ + return ret; +} +wtype KruskalSec() { + wtype ret = INF; + for (int x = 0; x < n - 1; x++) { + memset(fa, -1, sizeof(fa)); + int cnt = 0; wtype tmp = 0; + for (int i = 0; i < tot; i++) { + if (i != path[x]) { + int u = edge[i].u, v = edge[i].v, t1 = findfa(u), t2 = findfa(v); wtype w = edge[i].w; + if (t1 != t2) { tmp += w; fa[t1] = t2; cnt++; } + if (cnt == n - 1) { if (tmp < ret) { ret = tmp; } break; } + } + } + } + if (ret == INF) { return -1; } // + return ret; +} +//Сͼ +//㷨 O(VE) +typedef int wtype; +const int N = 1005; +const int M = 40005; +const wtype INF = 0x3f3f3f3f; +struct Edge { int u, v; wtype w; } edge[M]; +int n, m, pre[N], id[N], vis[N]; +wtype g[N][N], in[N]; +wtype Zhuliu(int root) { + wtype res = 0; int u, v; + for (;;) { + memset(in, 0x3f, sizeof(in)); + memset(id, -1, sizeof(id)); + memset(vis, -1, sizeof(vis)); + for (int i = 0; i < m; i++) { + if (edge[i].u != edge[i].v && edge[i].w < in[edge[i].v]) { + pre[edge[i].v] = edge[i].u; in[edge[i].v] = edge[i].w; + } + } + for (int i = 0; i < n; i++) { + if (i != root && in[i] == INF) { return -1; } //Сͼ + } + int tn = 0; in[root] = 0; + for (int i = 0; i < n; i++) { + res += in[i]; v = i; + while (vis[v] != i && id[v] == -1 && v != root) { + vis[v] = i; v = pre[v]; + } + if (v != root && id[v] == -1) { + for (int u = pre[v]; u != v ; u = pre[u]) { id[u] = tn; } + id[v] = tn++; + } + } + if (tn == 0) { break; } //û + for (int i = 0; i < n; i++) { + if (id[i] == -1) { id[i] = tn++; } + } + for (int i = 0; i < m;) { + v = edge[i].v; edge[i].u = id[edge[i].u]; edge[i].v = id[edge[i].v]; + if (edge[i].u != edge[i].v) { edge[i++].w -= in[v]; } + else { swap(edge[i], edge[--m]); } + } + n = tn; root = id[root]; + } + return res; +} +//POJ 3164 +int main() { + int C = 0, T, u, v, w; + scanf("%d", &T); + while (++C <= T) { + memset(g, 0x3f, sizeof(g)); + scanf("%d%d", &n, &m); + while (m--) { + scanf("%d%d%d", &u, &v, &w); + if (u == v) { continue; } + g[u][v] = min(g[u][v], w); + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (g[i][j] < INF) { edge[m].u = i; edge[m].v = j; edge[m++].w = g[i][j]; } + } + } + wtype ans = Zhuliu(0); + printf("Case #%d: ", C); + if (ans == -1) { puts("Possums!"); } + else { printf("%d\n", ans); } + } +} +//پС +//Kruskal O(VlogV) +const int INF = 0x3f3f3f3f; +struct Point { + int x, y, id; + bool operator<(const Point &r)const { return x < r.x || (x == r.x && y < r.y); } +} p[N]; +struct Edge { //Ч + int u, v, w; + bool operator<(const Edge &r)const { return w < r.w; } +} edge[N << 2]; +struct BIT { //״, y-xڵǰ, y+xС + int min_val, pos; + void init() { min_val = INF; pos = -1; } +} bit[N]; +int n, tot, fa[N]; +int a[N], b[N]; +void addedge(int u, int v, int w) { edge[tot].u = u; edge[tot].v = v; edge[tot++].w = w; } +int findfa(int x) { return fa[x] == -1 ? x : fa[x] = findfa(fa[x]); } +inline int cost(Point a, Point b) { return abs(a.x - b.x) + abs(a.y - b.y); } +inline int lowbit(int x) { return x & (-x); } +void update(int i, int val, int pos) { + for (; i > 0; i -= lowbit(i)) { + if (val < bit[i].min_val) { bit[i].min_val = val; bit[i].pos = pos; } + } +} +int query(int i, int m) { //ѯ[i, m]Сֵλ + int min_val = INF, pos = -1; + for (; i <= m; i += lowbit(i)) { + if (bit[i].min_val < min_val) { min_val = bit[i].min_val; pos = bit[i].pos; } + } + return pos; +} +void MMST() { + tot = 0; + for (int d = 0; d < 4; d++) { //4任 + if (d == 1 || d == 3) { for (int i = 0; i < n; i++) { swap(p[i].x, p[i].y); } } + else if (d == 2) { for (int i = 0; i < n; i++) { p[i].x = -p[i].x; } } + sort(p, p + n); + for (int i = 0; i < n; i++) { a[i] = b[i] = p[i].y - p[i].x; } + sort(b, b + n); + int m = unique(b, b + n) - b; + for (int i = 1; i <= m; i++) { bit[i].init(); } + for (int i = n - 1 ; i >= 0; i--) { + int pos = lower_bound(b, b + m, a[i]) - b + 1, ans = query(pos, m); + if (ans != -1) { addedge(p[i].id, p[ans].id, cost(p[i], p[ans])); } + update(pos, p[i].x + p[i].y, i); + } + } +} +int Kruskal() { + MMST(); + memset(fa, -1, sizeof(fa)); + sort(edge, edge + tot); + int ret = 0; + for (int i = 0, k = 0; i < tot; i++) { + int u = edge[i].u, v = edge[i].v, t1 = findfa(u), t2 = findfa(v); + if (t1 != t2) { + fa[t1] = t2; ret += edge[i].w; + if (++k == n - 1) { return ret; } + } + } +} +//POJ3241 Сϵkı +int Kruskal(int k) { + MMST(n, p); + memset(fa, -1, sizeof(fa)); + sort(edge, edge + tot); + for (int i = 0; i < tot; i++) { + int u = edge[i].u, v = edge[i].v, t1 = findfa(u), t2 = findfa(v); + if (t1 != t2) { + fa[t1] = t2; + if (--k == 0) { return edge[i].w; } + } + } +} +// +//Matrix-Tree(Kirchhoff -) +//1GĶD[G]һn*nľ, : i jʱ,dij = 0; i = jʱ, dijviĶ +//2GڽӾA[G]Ҳһn*nľ, : vi vj֮бֱ, aij = 1, Ϊ0 +//ǶGKirchhoff(ҲΪ˹)C[G]ΪC[G] = D[G] - A[G], Matrix-Tree +//Ϊ: GвͬĸKirchhoffC[G]κһn - 1ʽʽľֵ +//νn - 1ʽ, Ƕr(1 r n), C[G]ĵrСrͬʱȥõ¾, Cr[G]ʾ + + +============ͼ-========= +// +//SAP + ڽӾ O(V^2*E) ıĬϴ0ʼ +typedef long long ftype; +int n, dis[N], pre[N], cur[N], gap[N]; +ftype cap[N][N]; +ftype SAP(int src, int sink, int n) { + memset(dis, 0, sizeof(dis)); + memset(cur, 0, sizeof(cur)); + memset(gap, 0, sizeof(gap)); + int u = src; ftype mxflow = 0, aug = -1; pre[src] = src; gap[0] = n; + while (dis[src] < n) { +loop: + for (int v = cur[u]; v < n; ++v) { + if (cap[u][v] > 0 && dis[u] == dis[v] + 1) { + if (aug == -1 || aug > cap[u][v]) { aug = cap[u][v]; } + pre[v] = u; u = cur[u] = v; + if (v == sink) { + for (u = pre[u]; v != src; v = u, u = pre[u]) { + cap[u][v] -= aug; cap[v][u] += aug; + } + mxflow += aug; aug = -1; + } + goto loop; + } + } + int mndis = n - 1; + for (int v = 0; v < n; v++) { + if (cap[u][v] > 0 && mndis > dis[v]) { cur[u] = v; mndis = dis[v]; } + } + if (--gap[dis[u]] == 0) { break; } + dis[u] = mndis + 1; gap[dis[u]]++; u = pre[u]; + } + return mxflow; +} +//ISAP + ڽӱ O(V^2*E) +typedef long long ftype; +const ftype INF = 0x3f3f3f3f; +int head[N], to[M], nxt[M], tot, dis[N], pre[N], cur[N], gap[N]; +ftype cap[M]; +inline void init() { tot = 0; memset(head, -1, sizeof(head)); } +inline void addedge(int x, int y, ftype w, ftype rw = 0) { + to[tot] = y; cap[tot] = w; nxt[tot] = head[x]; head[x] = tot++; + to[tot] = x; cap[tot] = rw; nxt[tot] = head[y]; head[y] = tot++; +} +ftype ISAP(int src, int sink, int n) { + memset(dis, 0, sizeof(dis)); + memset(gap, 0, sizeof(gap)); + memcpy(cur, head, sizeof(head)); + int u = src, v; ftype mxflow = 0; pre[u] = -1; gap[0] = n; + while (dis[src] < n) { + if (u == sink) { + ftype mndis = INF; + for (int i = pre[u]; ~i; i = pre[to[i ^ 1]]) { + if (mndis > cap[i]) { mndis = cap[i]; } + } + for (int i = pre[u]; ~i; i = pre[to[i ^ 1]]) { + cap[i] -= mndis; cap[i ^ 1] += mndis; + } + u = src; mxflow += mndis; + continue; + } + bool flag = false; + for (int i = cur[u]; ~i; i = nxt[i]) { + v = to[i]; + if (cap[i] > 0 && dis[v] + 1 == dis[u]) { + flag = true; cur[u] = pre[v] = i; break; + } + } + if (flag) { u = v; continue; } + int mndis = n; + for (int i = head[u]; ~i; i = nxt[i]) { + if (cap[i] > 0 && dis[to[i]] < mndis) { mndis = dis[to[i]]; cur[u] = i; } + } + if (--gap[dis[u]] == 0) { return mxflow; } + dis[u] = mndis + 1; gap[dis[u]]++; + if (u != src) { u = to[pre[u] ^ 1]; } + } + return mxflow; +} +//ISAP + bfs + queue + ڽӱ O(V^2*E) +typedef long long ftype; +const ftype INF = 0x3f3f3f3f; +int n, head[N], to[M], nxt[M], tot, dis[N], pre[N], cur[N], gap[N]; +ftype cap[M]; +inline void init() { tot = 0; memset(head, -1, sizeof(head)); } +inline void addedge(int x, int y, ftype w, ftype rw = 0) { + to[tot] = y; cap[tot] = w; nxt[tot] = head[x]; head[x] = tot++; + to[tot] = x; cap[tot] = rw; nxt[tot] = head[y]; head[y] = tot++; +} +void bfs(int sink) { + memset(dis, -1, sizeof(dis)); + memset(gap, 0, sizeof(gap)); + dis[sink] = 0; gap[0] = 1; + queue que; que.push(sink); + while (!que.empty()) { + int u = que.front(); que.pop(); + for (int i = head[u], v; ~i; i = nxt[i]) { + v = to[i]; + if (~dis[v]) { continue; } + dis[v] = dis[u] + 1; gap[dis[v]]++; que.push(v); + } + } +} +ftype ISAP(int src, int sink, int n) { + bfs(sink); + memcpy(cur, head, sizeof(head)); + int u = pre[src] = src, v, i; ftype mxflow = 0; + while (dis[sink] < n) { + if (u == sink) { + ftype mndis = INF; int inser; + for (i = src; i != sink; i = to[cur[i]]) { + if (mndis > cap[cur[i]]) { mndis = cap[cur[i]]; inser = i; } + } + for (i = src; i != sink; i = to[cur[i]]) { + cap[cur[i]] -= mndis; cap[cur[i] ^ 1] += mndis; + } + mxflow += mndis; u = inser; + } + for (i = cur[u]; ~i; i = nxt[i]) { + v = to[i]; + if (dis[v] + 1 == dis[u] && cap[i] > 0) { break; } + } + if (~i) { cur[u] = i; pre[to[i]] = u; u = to[i]; } + else { + if (--gap[dis[u]] == 0) { break; } + int mndis = n; + for (i = head[u]; ~i; i = nxt[i]) { + if (cap[i] > 0 && mndis > dis[to[i]]) { cur[u] = i; mndis = dis[to[i]]; } + } + dis[u] = mndis + 1; gap[dis[u]]++; u = pre[u]; + } + } + return mxflow; +} +//Dinic O(V^2*E) +typedef long long ftype; +const ftype INF = 0x3f3f3f3f; +int head[N], to[M], nxt[M], tot, dis[N], cur[N], src, sink; +ftype cap[M]; +inline void init() { tot = 0; memset(head, -1, sizeof(head)); } +inline void addedge(int x, int y, ftype w, ftype rw = 0) { + to[tot] = y; cap[tot] = w; nxt[tot] = head[x]; head[x] = tot++; + to[tot] = x; cap[tot] = rw; nxt[tot] = head[y]; head[y] = tot++; +} +bool bfs() { + memset(dis, 0, sizeof(dis)); dis[src] = 1; + queue que; que.push(src); + while (!que.empty()) { + int u = que.front(); que.pop(); + for (int i = head[u], v; ~i; i = nxt[i]) { + v = to[i]; + if (cap[i] > 0 && !dis[v]) { dis[v] = dis[u] + 1; que.push(v); } + } + } + return dis[sink]; +} +ftype dfs(int u, ftype delta) { + if (u == sink || delta == 0) { return delta; } + ftype ret = 0; + for (int &i = cur[u], v; delta && ~i; i = nxt[i]) { + v = to[i]; + if (cap[i] > 0 && dis[v] == dis[u] + 1) { + ftype aug = dfs(v, min(cap[i], delta)); + if (!aug) { continue; } + cap[i] -= aug; cap[i ^ 1] += aug; delta -= aug; ret += aug; + if (!delta) { break; } + } + } + return ret; +} +ftype Dinic() { + ftype ret = 0; + while (bfs()) { + memcpy(cur, head, sizeof(head)); + ret += dfs(src, INF); + } + return ret; +} +//HLPP Highest Label Preflow Push O(V^3) +typedef long long ftype; +struct Edge { int v; ftype c; } edge[M]; +vector e[N]; +int n, m, src, sink, c[N << 1], d[N], done[N]; +ftype w[N]; +bool vis[N]; +void init(int _n, int _src, int _sink) { + n = _n; m = 0; src = _src; sink = _sink; + for (int i = 0; i <= n; ++i) { e[i].clear(); } +} +inline void addEdge(int x, int y, ftype w, ftype rw = 0) { + edge[m].v = y; edge[m].c = w; e[x].push_back(m++); + edge[m].v = x; edge[m].c = rw; e[y].push_back(m++); +} +void bfs() { + memset(c, 0, sizeof(c)); + fill(d, d + n, n + 1); + queue que; que.push(sink); + c[n + 1] = n - 1; d[src] = n; d[sink] = 0; + while (!que.empty()) { + int u = que.front(); que.pop(); + c[n + 1]++; c[d[u]]++; + for (int i = 0, v; i < (int)e[u].size(); i++) { + v = edge[e[u][i]].v; ftype c = edge[e[u][i] ^ 1].c; + if (d[v] == n + 1 && c > 0) { d[v] = d[u] + 1; que.push(v); } + } + } +} +int HLPP(int n) { + memset(w, 0, sizeof(w)); + memset(done, 0, sizeof(done)); + memset(vis, 0, sizeof(vis)); + bfs(); + int todo = -1; + vector> que(n << 1); + vis[src] = vis[sink] = true; + for (int i = 0, v; i < (int)e[src].size(); i++) { + Edge &arc = edge[e[src][i]], &cra = edge[e[src][i] ^ 1]; v = arc.v; + w[v] += arc.c; cra.c += arc.c; arc.c = 0; + if (!vis[v]) { vis[v] = true; que[d[v]].push(v); todo = max(todo, d[v]); } + } + while (todo >= 0) { + if (que[todo].empty()) { todo--; continue; } + int u = que[todo].front(); que[todo].pop(); + vis[u] = false; + while (done[u] < (int)e[u].size()) { + Edge &arc = edge[e[u][done[u]]]; int v = arc.v; + if (d[u] == d[v] + 1 && arc.c > 0) { + Edge &cra = edge[e[u][done[u]] ^ 1]; ftype f = min(w[u], arc.c); + w[u] -= f; w[v] += f; arc.c -= f; cra.c += f; + if (!vis[v]) { vis[v] = true; que[d[v]].push(v); } + if (w[u] == 0) { break; } + } + done[u]++; + } + if (w[u] > 0) { + int du = d[u]; + c[d[u]]--; d[u] = n << 1; + for (int i = 0, v; i < (int)e[u].size(); i++) { + Edge &arc = edge[e[u][i]]; v = arc.v; + if (d[u] > d[v] + 1 && arc.c > 0) { d[u] = d[v] + 1; done[u] = i; } + } + c[d[u]]++; + if (c[du] == 0) { + for (int i = 0; i < n; ++i) { + if (d[i] > du && d[i] < n + 1) { c[d[i]]--; c[n + 1]++; d[i] = n + 1; } + } + } + vis[u] = true; que[d[u]].push(u); todo = d[u]; + } + } + return w[sink]; +} +//½ +//Դ½ +//ӳԴ, ߵΪԭϽȥ½IJ, ¼ÿ½-½ +//½ʹ0ʱһԴ㵽ı, Ϊ½ +//½С0ʱһ㵽ı, Ϊ½͵ľֵ +//һ, ԴijĻ, , 򲻴 +//Դ½ +//ӻһINFıߵԴ, ԴתΪԴ +//жǷ, ȥԴ㼰(head[]ɾ, 㷨ʱ, ҪԴ) +//һԭԴԭ, +//Դ½С +//ӳԴ, һ鳬Դ +//ԭһINFıߵԭԴ, һ鳬Դ +//ҽԴijʱпн, Ϊԭ㵽ԭԴķ +////С MCMF O(V*E*f) +//С: dis[sink]Ϊ +//С: dis[sink]ΪINF +//ֻȡ෴, ȡ෴ +typedef long long ftype; +const ftype INF = 0x3f3f3f3f; +int head[N], to[M], nxt[M], tot, cur[N]; +ftype cap[M], cost[M], flow[N], dis[N], mncost, mxflow; +bool vis[N]; +inline void init() { tot = 0; memset(head, -1, sizeof(head)); } +inline void addedge(int x, int y, ftype w, ftype c) { + to[tot] = y; cap[tot] = w; cost[tot] = c; nxt[tot] = head[x]; head[x] = tot++; + to[tot] = x; cap[tot] = 0; cost[tot] = -c; nxt[tot] = head[y]; head[y] = tot++; +} +bool SPFA(int src, int sink) { + memset(dis, 0x3f, sizeof(dis)); + memset(vis, 0, sizeof(vis)); + dis[src] = 0; cur[src] = -1; flow[src] = INF; + queue que; que.push(src); + while (!que.empty()) { + int u = que.front(); que.pop(); + vis[u] = false; + for (int i = head[u], v; ~i; i = nxt[i]) { + v = to[i]; + if (cap[i] > 0 && dis[v] > dis[u] + cost[i]) { + dis[v] = dis[u] + cost[i]; flow[v] = min(flow[u], cap[i]); cur[v] = i; + if (!vis[v]) { vis[v] = true; que.push(v); } + } + } + } + if (dis[sink] == INF) { return false; } + mxflow += flow[sink]; mncost += flow[sink] * dis[sink]; + for (int i = cur[sink]; ~i; i = cur[to[i ^ 1]]) { + cap[i] -= flow[sink]; cap[i ^ 1] += flow[sink]; + } + return true; +} +ftype MCMF(int src, int sink) { + mxflow = mncost = 0; + while (SPFA(src, sink)); + return mncost; +} + +===========ͼ-Ӧ========== +// O(V^2) +//queue->ͨж, priority_queue->ֵ +//ڽӾ +int n, mp[N][N], in[N], ret[N]; +int topoSort() { + queue que; int k = 0; bool flag = false; + for (int i = 0; i < n; i++) { if (in[i] == 0) { que.push(i); } } + while (!que.empty()) { + if (que.size() > 1) { flag = true; } + int u = que.front(); que.pop(); ret[k++] = u; + for (int v = 0; v < n; v++) { + if (mp[u][v] && --in[v] == 0) { que.push(v); } + } + } + return k < n ? -1 : flag ? 0 : 1; //л, Ψһ, Ψһ +} +//ڽӱ +int head[N], to[M], nxt[M], tot, n, in[N], ret[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } +bool topoSort() { + priority_queue que; int k = 0; + for (int i = 0; i < n; i++) { if (in[i] == 0) { que.push(i); } } + while (!que.empty()) { + int u = que.top(); que.pop(); ret[k++] = u; + for (int i = head[u]; ~i; i = nxt[i]) { + if (--in[to[i]] == 0) { que.push(to[i]); } + } + } + return k == n; +} +//Ⱦɫж϶ͼ +bool col[N]; +bool Color(int u) { + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (!col[v]) { + col[v] = !col[u]; + if (!Color(v)) { return false; } + } else if (col[v] == col[u]) { return false; } + } + return true; +} +//ŷ·: ÿֻһ, Ҫص +//ŷ·: ÿֻһ, Ҫص +//ŷ·ж: +//ͼ: ͨ(ǶΪ0ĵ), ÿΪżҽĶΪż +//ͼ: ͼͨ(ѱߵ, ͬǶΪ0ĵ), ÿȵ +//ҽһijȱȶ1, ҽһijȱ1, ȵ +//ͼ: ŷ·, һŷ·ˡҽ( - ), +//ôӱ, жǷŷ· +//ŷ·ж: +//ͼ: ͨ(ǶΪ0ĵ), ÿΪż +//ͼ: ͼͨ(ͬǶΪ0ĵ), ÿȵ +//ͼ: ͼͨ(ǶΪ0ĵ), Ȼж +//ȸԭͼеÿָһ, ԭͼΪͼG' +//D[i]ΪG'(iij - i), D[i]Ϊ, ͼͨ, ޽ +//ʼDֵż, G'װ: ԴSͻT +//ÿD[i] > 0ĵi, , ΪD[i] / 2; ÿD[j] < 0ĵj, , Ϊ-D[j] / 2 +//G'еÿԱ, Ϊ1, , Sб߾, ԭͼŷͼ +//Ϊ1IJSTıG'иı䷽,γɵͼG''һŷͼ +//ŷ· + ڽӾ O(N^2) +//ŷ·/·ĵ ֧Իر +int n, mp[N][N], path[N], cnt; +void dfsu(int u) { + for (int v = n - 1; v >= 0; v--) { + while (mp[u][v]) { mp[u][v]--; mp[v][u]--; dfsu(v); } + } + path[cnt++] = u; +} +void dfsd(int u) { + for (int v = n - 1; v >= 0; v--) { + while (mp[u][v]) { mp[u][v]--; dfsd(v); } + } + path[cnt++] = u; +} +//ͼ SGU101 +int head[N], to[M], nxt[M], tot, deg[N], path[M], cnt; +bool vis[M]; +void init() { + tot = 0; cnt = 0; + memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); memset(deg, 0, sizeof(deg)); +} +void addedge(int x, int y) { + to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; + to[tot] = x; nxt[tot] = head[y]; head[y] = tot++; +} +void dfs(int u) { + for (int &i = head[u]; ~i;) { + if (!vis[i]) { vis[i] = vis[i ^ 1] = true; int t = i; dfs(to[i]); path[cnt++] = t; } + else { i = nxt[i]; } + } +} +int main() { + int n, u, v; + while (~scanf("%d", &n)) { + init(); + for (int i = 0; i < n; i++) { + scanf("%d%d", &u, &v); addedge(u, v); deg[u]++; deg[v]++; + } + int s = -1, cnto = 0; + for (int i = 0; i <= 6; i++) { + if (s == -1 && deg[i] > 0) { s = i; } + if (deg[i] & 1) { cnto++; s = i; } + } + if (cnto != 0 && cnto != 2) { puts("No solution"); continue; } + dfs(s); + if (cnt != n) { puts("No solution"); continue; } + for (int i = 0; i < cnt; i++) { + printf("%d %c\n", (path[i] >> 1) + 1, path[i] & 1 ? '+' : '-'); + } + } +} +//ͼ POJ2337 +//nСдĸɵĵ, Ҫn, ֵСĽ +int head[N], to[M], nxt[M], tot, in[N], out[N], path[N], cnt; +bool vis[M]; +string str[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { + to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; +} +void dfs(int u) { + for (int &i = head[u]; ~i;) { + if (!vis[i]) { vis[i] = true; int t = i; dfs(to[i]); path[cnt++] = n - t - 1; } + else { i = nxt[i]; } + } +} +int main() { + int T, n; + char s[25]; + scanf("%d", &T); + while (T--) { + init(); cnt = 0; + memset(vis, 0, sizeof(vis)); + memset(in, 0, sizeof(in)); + memset(out, 0, sizeof(out)); + scanf("%d", &n); + for (int i = 0; i < n; i++) { scanf("%s", s); str[i] = s; } + sort(str, str + n); + int s = 26; + for (int i = n - 1; i >= 0; i--) { //ֵȼ + int u = str[i][0] - 'a', v = str[i][str[i].size() - 1] - 'a'; + addedge(u, v); out[u]++; in[v]++; + s = min(s, min(u, v)); + } + int cnt1 = 0, cnt2 = 0; + for (int i = 0; i < 26; i++) { + if (out[i] - in[i] == 1) { cnt1++; s = i; } //һȱȴ1ĵ, ʹ, Сĵ + else if (out[i] - in[i] == -1) { cnt2++; } + else if (out[i] - in[i] != 0) { cnt1 = 3; } + } + if (!((cnt1 == 0 && cnt2 == 0) || (cnt1 == 1 && cnt2 == 1))) { puts("***"); continue; } + dfs(s); + if (cnt != n) { puts("***"); continue; } + for (int i = cnt - 1; i >= 0; i--) { + printf("%s%c", str[path[i]].c_str(), i > 0 ? '.' : '\n'); + } + } +} +//ͼ 鼯 HDU1116 +//жеܲһ, жظĵ, Ҳ +int n, fa[N], in[N], out[N], p[N]; +bool vis[N]; +char s[M]; +void init() { + memset(vis, 0, sizeof(vis)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); + for (int i = 0; i < N; i++) { fa[i] = i; } +} +int findfa(int n) { + return n == fa[n] ? n : fa[n] = findfa(fa[n]); +} +inline void unite(int x, int y) { + x = findfa(x); y = findfa(y); + if (x != y) { fa[y] = x; } +} +int main() { + int T, n; + scanf("%d", &T); + while (T--) { + init(); + scanf("%d", &n); + while (n--) { + scanf("%s", s); int u = s[0] - 'a', v = s[strlen(s) - 1] - 'a'; + unite(u, v); out[u]++; in[v]++; vis[u] = vis[v] = true; + } + int cnt = 0, k = 0; + for (int i = 0; i < N; i++) { + fa[i] = findfa(i); + if (vis[i] && fa[i] == i) { cnt++; } + } + if (cnt > 1) { puts("The door cannot be opened."); continue; } //ͨ + for (int i = 0; i < N; i++) { + if (in[i] != out[i]) { p[k++] = i; if (k > 2) { break; } } + } + if (k == 0 || (k == 2 && ((out[p[0]] - in[p[0]] == 1 && in[p[1]] - out[p[1]] == 1) || + (out[p[1]] - in[p[1]] == 1 && in[p[0]] - out[p[0]] == 1)))) { + puts("Ordering is possible."); + } else { puts("The door cannot be opened."); } + } +} +//ͼ POJ1637 (Ᵽ֤ͨ) +//жŷ· ISAP + ڽӱ O(V^2*E) +int in[N], out[N]; +int main() { + int T, u, v, w; + scanf("%d", &T); + while (T--) { + init(); + memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); + scanf("%d%d", &n, &m); + while (m--) { + scanf("%d%d%d", &u, &v, &w); out[u]++; in[v]++; + if (w == 0) { addedge(u, v, 1); } //˫ + } + bool flag = true; + for (int i = 1; i <= n; i++) { + if (out[i] - in[i] > 0) { addedge(0, i, (out[i] - in[i]) >> 1); } + else if (in[i] - out[i] > 0) { addedge(i, n + 1, (in[i] - out[i]) >> 1); } + if (out[i] - in[i] & 1) { flag = false; break; } + } + if (!flag) { puts("impossible"); continue; } + ISAP(0, n + 1, n + 2); + for (int i = head[0]; ~i; i = nxt[i]) { + if (cap[i] > 0 && cap[i] > flow[i]) { flag = false; break; } + } + puts(flag ? "possible" : "impossible"); + } +} +//2-SAT +//Ⱦɫ +const int N = 20005; +const int M = 100005; +int head[N], to[M], nxt[M], tot; +bool vis[N]; //Ⱦɫ +int S[N], top; //ջ +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } +bool dfs(int u) { + if (vis[u ^ 1]) { return false; } + if (vis[u]) { return true; } + vis[u] = true; S[top++] = u; + for (int i = head[u]; ~i; i = nxt[i]) { + if (!dfs(to[i])) { return false; } + } + return true; +} +bool twoSAT(int n) { + memset(vis, 0, sizeof(vis)); + for (int i = 0; i < n; i += 2) { + if (vis[i] || vis[i ^ 1]) { continue; } + top = 0; + if (!dfs(i)) { + while (top) { vis[S[--top]] = false; } + if (!dfs(i ^ 1)) { return false; } + } + } + return true; +} +//HDU 1814 +int main() { + int n, m, u, v; + while (~scanf("%d%d", &n, &m)) { + init(); + while (m--) { + scanf("%d%d", &u, &v); u--; v--; + addedge(u, v ^ 1); addedge(v, u ^ 1); + } + if (twoSAT(n << 1)) { + for (int i = 0; i < n << 1; i++) { + if (vis[i]) { printf("%d\n", i + 1); } + } + } else { printf("NIE\n"); } + } +} +//Tarjanǿͨ +const int N = 1005; +const int M = 100005; +int head[N], to[M], nxt[M], tot; +int num[N], Low[N], DFN[N], S[N], Belong[N], idx, top, scc; //Belongֵ1~scc +bool instack[N]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } +void Tarjan(int u) { + Low[u] = DFN[u] = ++idx; S[top++] = u; instack[u] = true; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (!DFN[v]) { Tarjan(v); Low[u] = min(Low[u], Low[v]); } + else if (instack[v] && Low[u] > DFN[v]) { Low[u] = DFN[v]; } + } + if (Low[u] == DFN[u]) { + scc++; + do { v = S[--top]; instack[v] = false; Belong[v] = scc; num[scc]++; } while (v != u); + } +} +bool solvable(int n) { //nܸ, Ҫѡһ + memset(DFN, 0, sizeof(DFN)); + memset(instack, 0, sizeof(instack)); + memset(num, 0, sizeof(num)); + idx = scc = top = 0; + for (int i = 0; i < n; i++) { if (!DFN[i]) { Tarjan(i); } } + for (int i = 0; i < n; i += 2) { if (Belong[i] == Belong[i ^ 1]) { return false; } } + return true; +} +//һⲿ +queue q1, q2; +vector> dag; //DAGͼ +char color[N]; //Ⱦɫ, Ϊ'R'ѡ +int cf[N], indeg[N]; // +void solve(int n) { + dag.assign(scc + 1, vector()); + memset(indeg, 0, sizeof(indeg)); + memset(color, 0, sizeof(color)); + for (int u = 0; u < n; u++) { + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (Belong[u] != Belong[v]) { dag[Belong[v]].push_back(Belong[u]); indeg[Belong[u]]++; } + } + } + for (int i = 0; i < n; i += 2) { + cf[Belong[i]] = Belong[i ^ 1]; cf[Belong[i ^ 1]] = Belong[i]; + } + while (!q1.empty()) { q1.pop(); } + while (!q2.empty()) { q2.pop(); } + for (int i = 1; i <= scc; i++) { if (indeg[i] == 0) { q1.push(i); } } + while (!q1.empty()) { + int u = q1.front(); q1.pop(); + if (color[u] == 0) { color[u] = 'R'; color[cf[u]] = 'B'; } + for (int i = 0; i < (int)dag[u].size(); i++) { + if (--indeg[dag[u][i]] == 0) { q1.push(dag[u][i]); } + } + } +} +int change(char s[]) { + int ret = 0, i = 0; + while (s[i] >= '0' && s[i] <= '9') { ret *= 10; ret += s[i++] - '0'; } + return (ret << 1) + (s[i] != 'w'); +} +//POJ3648 +int main() { + int n, m, u, v; + char s1[10], s2[10]; + while (scanf("%d%d", &n, &m), (n || m)) { + init(); + while (m--) { + scanf("%s%s", s1, s2); u = change(s1); v = change(s2); + addedge(u ^ 1, v); addedge(v ^ 1, u); + } + addedge(1, 0); + if (solvable(n << 1)) { + solve(n << 1); + for (int i = 1; i < n; i++) { + //עһжcolor[Belong[ + if (color[Belong[i << 1]] == 'R') { printf("%dw", i); } + else { printf("%dh", i); } + putchar(i != n - 1 ? ' ' : '\n'); + } + } else { printf("bad luck\n"); } + } +} +// +// O(n*2^n) +int mp[N][N], stk[N][N], dp[N], ans; +bool dfs(int crt, int tot) { + if (!crt) { + if (tot > ans) { ans = tot; return true; } + return false; + } + for (int i = 0, u, nxt; i < crt; i++) { + u = stk[tot][i]; nxt = 0; + if (crt - i + tot <= ans) { return false; } + if (dp[u] + tot <= ans) { return false; } + for (int j = i + 1; j < crt; j++) { + int v = stk[tot][j]; + if (g[u][v]) { stk[tot + 1][nxt++] = v; } + } + if (dfs(nxt, tot + 1)) { return true; } + } + return false; +} +int maxClique(int n) { + ans = 0; + for (int i = n - 1, j, k; i >= 0; i--) { + for (j = i + 1, k = 0; j < n; j++) { + if (g[i][j]) { stk[1][k++] = j; } + } + dfs(k, 1); dp[i] = ans; + } + return ans; +} +//̰ O(T*n^2) +const int T = 1000; +int mp[N][N], id[N], ansn, ans[N]; bool del[N]; +void solve(int n) { + memset(del, 0, sizeof(del)); int k = 0; + for (int i = 0, j; i < n; i++) { + if (del[i]) { continue; } + for (j = i + 1, k++; j < n; j++) { if (!mp[id[i]][id[j]]) { del[j] = true; } } + } + if (k > ansn) { + ansn = k; + for (int i = k = 0; i < n; i++) { if (!del[i]) { ans[k++] = id[i]; } } + } +} +void maxClique(int n) { + for (int i = 0; i < n; i++) { id[i] = i; } + for (int t = 0; t < T; t++) { + for (int i = 0; i < n; i++) { swap(id[i], id[rand() % n]); } solve(); + } +} +// +//㷨 O(T*(V+E)) +const int T = 1000; +int q[N], pos[N]; bool del[N]; +int solve(int n) { + int ans = 0; + for (int t = 0; t < T; t++) { + int ret = 0, top = n; memset(del, 0, sizeof(del)); + for (int i = 1; i <= n; i++) { q[i] = pos[i] = i; } + while (top) { + int x = rand() % top + 1, u = q[x]; q[x] = q[top--]; pos[q[x]] = x; ret++; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (!del[v]) { del[v] = true; x = pos[v]; q[x] = q[top--]; pos[q[x]] = x; } + } + } + ans = max(ans, ret); + } + return ans; +} + +==========ͼ-·========= +//ڽӱ +typedef int wtype; +const wtype INF = 0x3f3f3f3f; +int head[N], to[M], nxt[M], tot; wtype len[M]; +void init() { tot = 0; memset(head, -1, sizeof(head)); } +void addedge(int x, int y, wtype z) { to[tot] = y; len[tot] = z; nxt[tot] = head[x]; head[x] = tot++; } +//Dijkstra + priority_queue + ڽӾ O(V^2) +typedef int wtype; +struct Node { + int v; wtype w; + bool operator<(const Node &r)const { return w > r.w; } +}; +int n, pre[N]; wtype mp[N][N], dist[N]; bool vis[N]; //ڽӾʼΪINF +void Dijkstra(int src) { + memset(dist, 0x3f, sizeof(dist)); + memset(vis, 0, sizeof(vis)); memset(pre, -1, sizeof(pre)); + priority_queue que; que.push((Node) {src, dist[src] = 0}); + while (!que.empty()) { + int u = que.top().v; que.pop(); + if (vis[u]) { continue; } + vis[u] = true; + for (int v = 0; v < n; v++) { + if (!vis[v] && dist[v] > dist[u] + mp[u][v]) { + dist[v] = dist[u] + mp[u][v]; pre[v] = u; que.push((Node) {v, dist[v]}); + } + } + } +} +//Dijkstra + priority_queue + vector O((V+E)logV) +typedef int wtype; +struct Node { + int v; wtype w; + bool operator<(const Node &r)const { return w > r.w; } +}; +vector e[N]; wtype dist[N]; bool vis[N]; +void Dijkstra(int src) { + memset(dist, 0x3f, sizeof(dist)); + memset(vis, 0, sizeof(vis)); + priority_queue que; que.push((Node) {src, dist[src] = 0}); + while (!que.empty()) { + int u = que.top().v; que.pop(); + if (vis[u]) { continue; } + vis[u] = true; + for (int i = 0; i < (int)e[u].size(); i++) { + int v = e[u][i].v; wtype w = e[u][i].w; + if (!vis[v] && dist[v] > dist[u] + w) { + dist[v] = dist[u] + w; que.push((Node) {v, dist[v]}); + } + } + } +} +//Dijkstra + priority_queue + ڽӱ O((V+E)logV) +typedef int wtype; +struct Node { + int v; wtype w; + bool operator<(const Node &r)const { return w > r.w; } +}; +wtype dist[N]; +void Dijkstra(int src) { + memset(dist, 0x3f, sizeof(dist)); + priority_queue que; que.push((Node) {src, dist[src] = 0}); + while (!que.empty()) { + int u = que.top().v; wtype w = que.top().w; que.pop(); + if (w > dist[u]) { continue; } + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; + if (dist[v] > len[i] + w) { + dist[v] = w + len[i]; que.push((Node) {v, dist[v]}); + } + } + } +} +//SPFA + queue/stack + vector O(kE) +typedef int wtype; +struct Edge { int v; wtype w; }; +vector e[N]; int cnt[N], pre[N]; wtype dist[N]; bool vis[N]; +bool SPFA(int src) { + memset(dist, 0x3f, sizeof(dist)); dist[src] = 0; + memset(cnt, 0, sizeof(cnt)); cnt[src] = 1; + memset(vis, 0, sizeof(vis)); vis[src] = true; + memset(pre, -1, sizeof(pre)); + queue que; que.push(src); //stack + while (!que.empty()) { + int u = que.front(); que.pop(); + vis[u] = false; + for (int i = 0; i < (int)e[u].size(); i++) { + int v = e[u][i].v; wtype w = e[u][i].w; + if (dist[v] > dist[u] + w) { + dist[v] = dist[u] + w; pre[v] = u; + if (!vis[v]) { + vis[v] = true; que.push(v); + if (++cnt[v] > n) { return false; } //и· + } + } + } + } + return true; //ûи· +} +//SPFA + SLF + LLL + ڽӱ O(kE) +typedef int wtype; +wtype dist[N]; +bool vis[M]; +void SPFA(int src) { + memset(dist, 0x3f, sizeof(dist)); dist[src] = 0; + memset(vis, 0, sizeof(vis)); vis[src] = true; + deque que; que.push_back(src); + ll sum = 0; + while (!que.empty()) { + int u = que.front(); que.pop_front(); + if (!que.empty() && (ll)dist[u] * que.size() > sum) { que.push_back(u); continue; } + sum -= dist[u]; vis[u] = false; + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; wtype d = dist[u] + len[i]; + if (d < dist[v]) { + if (vis[v]) { sum += d - dist[v]; } + dist[v] = d; + if (!vis[v]) { + if (!que.empty() && dist[que.front()] > dist[v]) { que.push_front(v); } + else { que.push_back(v); } + sum += dist[v]; vis[v] = true; + } + } + } + } +} +//Լϵͳ +//abһȨֵΪc߱ʾb ? a <= c, SPFAжǷڸ, ڼ޽ +//Bellman-Ford + vector O(VE) +//ԴȨͼ, жǷڸ·, ҽͼвԴɴĸȨ·ʱtrue +typedef int wtype; +struct Edge { int u, v; wtype w; }; +vector e; +wtype dist[N]; +bool BellmanFord(int src) { + memset(dist, 0x3f, sizeof(dist)); dist[src] = 0; + for (int i = 1; i < n; i++) { + bool flag = false; + for (int j = 0; j < (int)e.size(); j++) { + int u = e[j].u, v = e[j].v; wtype w = e[j].w; + if (dist[v] > dist[u] + w) { dist[v] = dist[u] + w; flag = true; } + } + if (!flag) { return true; } //ûи· + } + for (int j = 0; j < (int)e.size(); j++) { + int u = e[j].u, v = e[j].v; wtype w = e[j].w; + if (dist[v] > dist[u] + w) { return false; } //и· + } + return true; //ûи· +} +//Floyd ·¼ O(V^3) +typedef int wtype; +int n, pre[N][N]; wtype mp[N][N]; //ʼΪINF +void Floyd() { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { pre[i][j] = (i == j) ? -1 : i; } + } + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (mp[i][k] + mp[k][j] < mp[i][j]) { + mp[i][j] = mp[i][k] + mp[k][j]; pre[i][j] = pre[k][j]; + } + } + } + } +} +//޸ȨͼС +//ͼ: mp[i][i] = INF, Ȼfloyd, ans = min(d[i][i]) +//ͼо3С: +typedef int wtype; +const wtype INF = 0x3f3f3f3f; +int n; wtype mp[N][N], d[N][N]; //ʼΪINF +wtype cycFloyd() { + memcpy(d, mp, sizeof(mp)); wtype ret = INF; + for (int k = 1; k <= n; k++) { + for (int i = 1; i < k; i++) { + for (int j = i + 1; j < k; j++) { + ans = min(ans, d[i][j] + mp[i][k] + mp[k][j]); + } + } + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + d[i][j] = min(d[i][j], d[i][k] + d[k][j]); + } + } + } +} +//Astark· +typedef int wtype; +const wtype INF = 0x3f3f3f3f; +int head[N], to[M], nxt[M], tot; wtype len[M]; +int rhead[N], rto[M], rnxt[M], rtot; wtype rlen[M]; +void init() { tot = rtot = 0; memset(head, -1, sizeof(head)); memset(rhead, -1, sizeof(rhead)); } +void addedge(int x, int y, wtype z) { + to[tot] = y; len[tot] = z; nxt[tot] = head[x]; head[x] = tot++; + rto[rtot] = x; rlen[rtot] = z; rnxt[rtot] = rhead[y]; rhead[y] = rtot++; +} +struct Node { + int v; wtype w; + bool operator<(const Node &r)const { return w > r.w; } +}; +int vis[N]; wtype dist[N], ans[N]; //ǰk· +void Astar(int src, int des, int k) { + memset(dist, 0x3f, sizeof(dist)); memset(ans, 0x3f, sizeof(ans)); memset(vis, 0, sizeof(vis)); + priority_queue que; que.push((Node) {des, dist[des] = 0}); + while (!que.empty()) { + int u = que.top().v; wtype w = que.top().w; que.pop(); + if (w > dist[u]) { continue; } + for (int i = rhead[u]; ~i; i = rnxt[i]) { + int v = rto[i]; + if (dist[v] > rlen[i] + w) { + dist[v] = w + rlen[i]; que.push((Node) {v, dist[v]}); + } + } + } + if (dist[src] < INF) { que.push((Node) {src, dis[src]}); } + while (!que.empty()) { + int u = que.top().v; wtype w = que.top().w; que.pop(); + if (u == des && vis[des] <= k) { ans[vis[des]] = w; } + if (vis[u] > k) { continue; } + for (int i = head[u]; ~i; i = nxt[i]) { + int v = to[i]; que.push((Node) {v, w - dist[u] + dist[v] + len[i]}); + } + } +} + + +===========Tarjan 㷨һͼ +int dfs[MAXN], low[MAXN], tim = 0; +inline void Dfs(int u) { + dfs[u] = low[u] = ++tim; + for (Edge *p = a[u]; p; p = p->next) if (p->flag) { + if (!dfs[p->y]) { + p->opt->flag = false; + Dfs(p->y); + low[u] = min(low[u], low[p->y]); + } else low[u] = min(low[u], dfs[p->y]); + } + for (Edge *p = a[u]; p; p = p->next) if (p->opt->flag == false && low[p->y] > dfs[u]) { + p->bridge = p->opt->bridge = true; + } +} + +=========Hopcroft 㷨жͼߵıΪ1-nұߵΪn+1 - Nmatch[i]ʾߵiƥϵұߵĵ㣬0ƥ䣬link[i]ʾұߵiƥϵߵĵ㣬0ƥ + +const int MAXN = 10000; +int match[MAXN]; +int levelx[MAXN], levely[MAXN], link[MAXN]; +int d[MAXN]; +inline bool Bfs(void) { + int head = 1, tail = 0; + memset(levely, 0, sizeof levely); + for (int i = 1; i <= n; i++) { + if (!match[i]) d[++tail] = i; + levelx[i] = 0; + } + bool ret = false; + while (head <= tail) { + int now = d[head++]; + for (Edge *p = a[now]; p; p = p->next) if (levely[p->y] == 0) { + levely[p->y] = levelx[now] + 1; + if (link[p->y] == 0) ret = true; + else levelx[link[p->y]] = levely[p->y] + 1, d[++tail] = link[p->y]; + } + } + return ret; +} +bool Find(int u) { + for (Edge *p = a[u]; p; p = p->next) if (levely[p->y] == levelx[u] + 1) { + levely[p->y] = 0; + if (link[p->y] == 0 || Find(link[p->y])) { + match[u] = p->y; link[p->y] = u; + return true; + } + } + return false; +} +inline void Match(void) { + while (Bfs()) + for (int i = 1; i <= n; i++) + if (!match[i]) Find(i); +} +inline void clear(void) { + memset(match, 0, sizeof match); + memset(link, 0, sizeof link); + memset(levelx, 0, sizeof levelx); + memset(levely, 0, sizeof levely); +} + + +=============KM㷨СȨƥ䣨עⲻȫȨƥ䣩ߵȻ߷ͼȨֵΪinfı + +Ȩƥ䣬򽫱Ȩȡ +const int MAXN = 210; +int nx, ny; // ߵĵŴ1nxұߵŴ1ny +long long inf, cost[MAXN][MAXN], fx[MAXN], fy[MAXN], dist[MAXN]; //ȨֵΪlong longĻֻĶм +int used[MAXN], maty[MAXN], which[MAXN]; +inline void AddEdge(int x, int y, int z) +{ + cost[x][y] = z; +} +pair KM(void) +{ + for (int x = 1; x <= nx; x++) + { + int y0 = 0; + maty[0] = x; + for (int y = 0; y <= ny; y++) + { + dist[y] = inf + 1; + used[y] = false; + } + do + { + used[y0] = true; + int x0 = maty[y0], y1; + long long delta = inf + 1; + for (int y = 1; y <= ny; y++) if (!used[y]) + { + long long curdist = cost[x0][y] - fx[x0] - fy[y]; + if (curdist < dist[y]) + { + dist[y] = curdist; + which[y] = y0; + } + if (dist[y] < delta) + { + delta = dist[y]; + y1 = y; + } + } + for (int y = 0; y <= ny; y++) if (used[y]) + { + fx[maty[y]] += delta; + fy[y] -= delta; + } + else dist[y] -= delta; + y0 = y1; + } + while (maty[y0] != 0); + do + { + int y1 = which[y0]; + maty[y0] = maty[y1]; + y0 = y1; + } + while (y0); + } + long long ret = 0; + int npair = 0; + for (int y = 1; y <= ny; y++) + { + int x = maty[y]; + if (cost[x][y] < inf) + { + ret += cost[x][y]; + npair++; + } + } + return make_pair(npair, ret); +} +inline void clear(void) +{ + memset(fx, 0x9f, sizeof fx); + memset(fy, 0x9f, sizeof fy); + memset(cost, 0x3f, sizeof cost); + memset(maty, 0, sizeof maty); + inf = cost[0][0]; +} + +==================DinicеǰŻ +struct Edge +{ + int y, f; + Edge *next, *opt; +}*a[MAXN], DATA[MAXM << 1], *data = DATA; +inline void Add(int x, int y, int c) +{ + Edge *tmp = data++; + tmp->y = y; + tmp->f = c, tmp->next = a[x]; + a[x] = tmp; + tmp = data++; + tmp->y = x; + tmp->f = 0; + tmp->next = a[y]; + a[y] = tmp; + a[x]->opt = a[y]; + a[y]->opt = a[x]; +} +int n, m, vs, vt, L; +int level[MAXN], d[MAXN]; +inline bool Bfs(void) +{ + memset(level, -1, sizeof level); + d[1] = vs; + level[vs] = 0; + int head = 1, tail = 1; + while (head <= tail) + { + int now = d[head++]; + e[now] = a[now]; + for (Edge *p = a[now]; p; p = p->next) if (p->f > 0&& level[p->y] == -1) + level[d[++tail] = p->y] = level[now] + 1; + } + return level[vt] != -1; +} +inline int Extend(int u, int sum) +{ + if (u == vt) return sum; + int r = 0, t; + for (Edge *p = e[u]; p && r < sum; p = p->next) if (level[p->y] == level[u] + 1 && p->f > 0) + { + t = std::min(sum - r, p->f); + t = Extend(p->y, t); + p->f -= t, p->opt->f += t, r += t; + e[u] = p; + } + if (!r) level[u] = -1; + return r; +} +inline int Dinic(void) +{ + int r = 0, t; + while (Bfs()) + { + while ((t = Extend(vs, inf))) r += t; + } + return r; +} + + +============spfaС +struct Edge +{ + int y, f, c; + Edge *next, *opt; + Edge(int y, int f, int c, Edge *next):y(y), f(f), c(c), next(next) {} +}*a[MAXN]; +inline void AddEdge(int x, int y, int f, int c) +{ + a[x] = new Edge(y, f, c, a[x]); + a[y] = new Edge(x, 0, -c, a[y]); + a[x]->opt = a[y]; + a[y]->opt = a[x]; +} +int d[MAXN], vis[MAXN], dis[MAXN]; +Edge *path[MAXN]; +inline pair Spfa(void) +{ + int Flow = 0, Cost = 0; + while (true) + { + memset(vis, 0, sizeof vis); + memset(dis, 0x7f, sizeof dis); + memset(path, 0, sizeof path); + int head = 1, tail = 1, sum = 1; + d[1] = vs; + vis[vs] = true; + dis[vs] = 0; + while (sum) + { + int now = d[head++]; + if (head == MAXN) head = 1; + sum--; + for (Edge *p = a[now]; p; p = p->next) if (p->f > 0 && dis[p->y] > dis[now] + p->c) + { + dis[p->y] = dis[now] + p->c; + path[p->y] = p; + if (!vis[p->y]) + { + ++tail; + if (tail == MAXN) tail = 1; + sum++; + d[tail] = p->y; + vis[p->y] = true; + } + } + vis[now] = false; + } + if (dis[vt] == dis[0]) return make_pair(Flow, Cost); + int tmp = vt, Min = ~0U>>1; + while (path[tmp]) + { + Min = min(Min, path[tmp]->f); + tmp = path[tmp]->opt->y; + } + Flow += Min; + tmp = vt; + while (path[tmp]) + { + path[tmp]->f -= Min; + path[tmp]->opt->f += Min; + Cost += Min * path[tmp]->c; + tmp = path[tmp]->opt->y; + } + } + return make_pair(Flow, Cost); +} + +================Сͼ㷨 +ʹڽӾͼ-1ʾСͼtmp[i].secondʾi +map[i][j] = 1 ʾʾһij +dis[i][j] ʾijߵij + +typedef pair PII; +PII tmp[MAXN]; +int dis[MAXN][MAXN]; +int map[MAXN][MAXN]; +int vis[MAXN], q[MAXN], inp[MAXN]; +int Dfs(int u) +{ + vis[u] = true; + int ret = 1; + for (int i = 1; i <= n; i++) if (map[u][i] && !vis[i]) ret += Dfs(i); + return ret; +} +int Zhuliu(void) +{ + memset(map, 0, sizeof map); + memset(vis, 0, sizeof vis); + if (Dfs(1) != n) return -1; + int done = 0; + while (true) + { + memset(vis, 0, sizeof vis); + memset(inp, 0, sizeof inp); + int Ans = 0; + for (int i = 1; i <= n; i++) vis[i] = i; + for (int i = 2; i <= n; i++) + { + tmp[i] = PII(1000000000, 0); + for (int j = 1; j <= n; j++) if (map[j][i] == 1) tmp[i] = min(tmp[i], PII(dis[j][i], j)); + inp[tmp[i].second]++; + if (tmp[i].second) Ans += tmp[i].first; + } + int head = 1, tail = 0; + for (int i = 1; i <= n; i++) if (!inp[i]) q[++tail] = i; + while (head <= tail) + { + int now = q[head++]; + if (!--inp[tmp[now].second]) q[++tail] = tmp[now].second; + } + bool ok = true; + for (int i = 1, t; i <= n; i++) if (inp[i] > 0) + { + t = i; + ok = false; + do + { + inp[t] = -i; + t = tmp[t].second; + vis[t] = i; + } + while (t != i); + } + if (ok) return Ans + done; + for (int i = 1; i <= n; i++) if (inp[i] < 0) + { + done += tmp[i].first; + for (int j = 1; j <= n; j++) if (vis[j] != vis[i]) + { + if (map[i][j]) + { + map[vis[i]][vis[j]] = 1; + dis[vis[i]][vis[j]] = min(dis[vis[i]][vis[j]], dis[i][j]); + } + if (map[j][i]) + { + dis[vis[j]][vis[i]] = min(dis[vis[j]][vis[i]], dis[j][i] - tmp[i].first); + map[vis[j]][vis[i]] = 1; + } + } + if (vis[i] != i) for (int j = 1; j <= n; j++) map[i][j] = map[j][i] = 0; + } + } +} + diff --git a/.ACM-Templates/TXTs/基础模板.txt b/.ACM-Templates/TXTs/基础模板.txt new file mode 100644 index 0000000..5f13cd2 --- /dev/null +++ b/.ACM-Templates/TXTs/基础模板.txt @@ -0,0 +1,1008 @@ +/** SPFA Դ·㷨 ָ֧*/ +namespace SPFA +{ +const int MAXN = 1005; +int d[MAXN];/// distance [ From S to ... ] +int v[MAXN];/// visit +int q[MAXN];/// Ķ(Ҳqueue...) +int mp[MAXN][MAXN]; /// mp[i][j] i --> j is connected. +int n;/// n is the number of max Point . + +void spfa(int StartPoint) /// d[i] is the min distance from StartPoint to i ( Both >=1 ) +{ + memset(d,0x3f,sizeof(d)); + memset(v,0,sizeof(v)); + /* + for(int i=1;i0) + { + int c=q[--cnt]; + v[c]=0; + for(int i=1;i<=n;i++) + { + /// Here : if your mp[i][j] use INF as infinite, then use mp[c][i]!=INF. + /// Or you may use mp[i][j]!=-1 && d[i] > d[c] + mp[c][i] + if( mp[c][i]!=INF && d[i]>d[c]+mp[c][i] ) + { + d[i]=d[c]+mp[c][i]; + if(!v[i]) v[i]=1,q[cnt++]=i; + } + } + } +} + +}/// End of NameSpace SPFA + + + +߶ģ(Powered By HC TECH - Kiritow) +include +/// General includes +#include +#include +#include + +#include +using namespace std; + +߶ +/// ߶: ,() +namespace SegmentTree +{ + +const int MAXN = 1000100; +const int MAXTREENODE = MAXN<<2; + +struct node +{ + int lt,rt; + int val; +}; + +node tree[MAXTREENODE]; + +/// _internal_v is a indexer of SegmentTree. It guides the procedure to the right node. + +void build(int L,int R,int _internal_v=1) /// Build a tree, _internal_v is 1 by default. +{ + tree[_internal_v].lt=L; + tree[_internal_v].rt=R; + if(L==R) + { + scanf("%d",&tree[_internal_v].val); + /// Or: tree[_internal].val = VAL_BY_DEFAULT + return; + } + int mid=(L+R)>>1; + build(L,mid,_internal_v<<1); + build(mid+1,R,_internal_v<<1|1);/// x<<1 == x*2; x<<1|1 == x*2+1; (faster == slower) + /// SegmentTree Main Algorithm + tree[_internal_v].val=tree[_internal_v<<1].val+tree[_internal_v<<1|1].val; +} + +void update(int Pos,int Val,int _internal_v=1)/// Update a position, _internal_v is 1 by default. +{ + if(tree[_internal_v].lt==tree[_internal_v].rt) + { + tree[_internal_v].val=Val; + return; + } + /// Update Deep-Loop + if(Pos <= tree[_internal_v<<1].rt) update(Pos,Val,_internal_v<<1); + if(Pos >= tree[_internal_v<<1|1].lt) update(Pos,Val,_internal_v<<1|1); + /// SegmentTree Main Algorithm + tree[_internal_v].val = tree[_internal_v<<1].val+tree[_internal_v<<1|1].val; +} + +int _internal_ans; +inline void _internal_clear_ans() +{ + _internal_ans=0; +} +inline int _internal_get_ans() +{ + return _internal_ans; +} +void basic_query(int L,int R,int _internal_v=1)/// Query A Segment [L,R] , _internal_v is 1 by default. +{ + if(tree[_internal_v].lt >= L && tree[_internal_v].rt <= R) + { + _internal_ans+=tree[_internal_v].val; + return; + } + if(L <= tree[_internal_v<<1].rt) basic_query(L,R,_internal_v<<1); + if(R >= tree[_internal_v<<1|1].lt) basic_query(L,R,_internal_v<<1|1); +} + +int query(int L,int R) +{ + _internal_clear_ans(); + basic_query(L,R); + return _internal_get_ans(); +} + +}/// End of namespace SegmentTree + +߶ +/// ӳٸ: 丳ֵ, () +namespace AttributeSegmentTree +{ + +const int MAXN = 100100; +const int MAXTREENODE = MAXN << 2; +const int ATTR_BY_DEFAULT=1;///Ĭϳʼ + +struct node +{ + int lt,rt; + int attr; +}; + +node tree[MAXTREENODE]; + +void build(int L,int R,int _indexer=1) +{ + tree[_indexer].lt=L; + tree[_indexer].rt=R; + tree[_indexer].attr=ATTR_BY_DEFAULT; + if(L!=R) + { + int mid=(L+R)>>1; + build(L,mid,_indexer<<1); + build(mid+1,R,_indexer<<1|1); + } +} + +void update(int L,int R,int NewAttr,int _indexer=1) +{ + if(tree[_indexer].attr==NewAttr) return; /// Same Attribute. Don't Need Change. + if(tree[_indexer].lt==L&&tree[_indexer].rt==R) + { + /// Right this segment. Update. + tree[_indexer].attr=NewAttr; + return; + } + /// This segment has only 1 attribute. New attribute is different. + /// So change this segment's manager's attribute to -1 ( Different Attribute in this segment ) + if(tree[_indexer].attr!=-1) + { + tree[_indexer<<1].attr=tree[_indexer<<1|1].attr=tree[_indexer].attr; + tree[_indexer].attr=-1; + } + /// If This segment has already had several attributes, operate its subtree by Deep-Loop. + int mid=(tree[_indexer].lt+tree[_indexer].rt)>>1; + if(L>mid) + { + update(L,R,NewAttr,_indexer<<1|1); + } + else if(R<=mid) + { + update(L,R,NewAttr,_indexer<<1); + } + else + { + update(L,mid,NewAttr,_indexer<<1); + update(mid+1,R,NewAttr,_indexer<<1|1); + } +} + +#define ValueOfAttr(Attr) (Attr) +int AttrSumUp(int _indexer=1) +{ + if(tree[_indexer].attr!=-1) + { + return ValueOfAttr(tree[_indexer].attr)*(tree[_indexer].rt-tree[_indexer].lt+1); + } + else + { + return AttrSumUp(_indexer<<1)+AttrSumUp(_indexer<<1|1); + } +} + +}/// End of namespace AttributeSegmentTree + +ɶθµ߶(LAZY˼) + +/// ӳٸ: (ӷ), () +namespace LazySegmentTree +{ + +const int MAXN = 100100; +const int MAXTREENODE = MAXN << 2; + +struct node +{ + int lt,rt; + int val; + int add; +}; + +node tree[MAXTREENODE]; + +void _internal_PushUp(int _indexer) +{ + tree[_indexer].val=tree[_indexer<<1].val+tree[_indexer<<1|1].val; +} +void _internal_PushDown(int _indexer) +{ + if(tree[_indexer].add!=0) + { + /// Broadcast this add value to Left and Right sub-tree node. + tree[_indexer<<1].add+=tree[_indexer].add; + tree[_indexer<<1|1].add+=tree[_indexer].add; + /// Confirm this change by calculate and add changes to sub-trees. + tree[_indexer<<1].val+=tree[_indexer].add * (tree[_indexer<<1].rt-tree[_indexer<<1].lt+1); + tree[_indexer<<1|1].val+=tree[_indexer].add *(tree[_indexer<<1|1].rt-tree[_indexer<<1|1].lt+1); + /// Now Clear this node's add value. + tree[_indexer].add=0; + } +} + +void build(int L,int R,int _indexer=1) +{ + tree[_indexer].lt=L; + tree[_indexer].rt=R; + tree[_indexer].add=0;/// This must be set to 0. + if(L==R) + { + //scanf("%d",&tree[_indexer].val); + tree[_indexer].val = 0; + return; + } + int mid=(L+R)>>1; + build(L,mid,_indexer<<1); + build(mid+1,R,_indexer<<1|1); + /// Update this val from down to up. (>.<) + _internal_PushUp(_indexer); +} + +void update(int L,int R,int ValToAdd,int _indexer=1) +{ + /// Return when L or R exceeds range. So smart ! + if(Rtree[_indexer].rt) return; + if(L<=tree[_indexer].lt&&R>=tree[_indexer].rt) + { + /// This range is covered. So just add the 'add' value, which is called "LAZY" + tree[_indexer].add+=ValToAdd; + tree[_indexer].val+=ValToAdd*(tree[_indexer].rt-tree[_indexer].lt+1); + return; + } + _internal_PushDown(_indexer); + /// This ... Hum.. Seems not so clever... + update(L,R,ValToAdd,_indexer<<1); + update(L,R,ValToAdd,_indexer<<1|1); + _internal_PushUp(_indexer); +} + +int ans; +void basic_query(int L,int R,int _indexer=1) +{ + /// Data to find is not in this range. + if(Rtree[_indexer].rt) return; + /// Data to find is right in this range , or covers this range. + if(L<=tree[_indexer].lt&&R>=tree[_indexer].rt) + { + ans+=tree[_indexer].val; + return ; + } + _internal_PushDown(_indexer); + int mid=(tree[_indexer].lt+tree[_indexer].rt)>>1; + if(R<=mid) + basic_query(L,R,_indexer<<1); + else if(L>mid) + basic_query(L,R,_indexer<<1|1); + else + { + basic_query(L,mid,_indexer<<1); + basic_query(mid+1,R,_indexer<<1|1); + } +} +int query(int L,int R) +{ + ans=0; + basic_query(L,R); + return ans; +} + +}/// End of namespace LazySegmentTree + +ɶθ£ϲ߶ +/// 丳ֵ, ϲ, +namespace AttributeMergeSegmentTree +{ + +const int MAXN = 100100; +const int MAXTREENODE = MAXN << 3; +const int ATTR_BY_DEFAULT=-1;///Ĭϳʼ -1 0 ס뿪 1 ס (POJ 3667) + +struct node +{ + int lt,rt; + int lsum,rsum,sum; + int attr; +}; + +node tree[MAXTREENODE]; + +void build(int L,int R,int _indexer=1) +{ + tree[_indexer].lt=L; + tree[_indexer].rt=R; + tree[_indexer].attr=ATTR_BY_DEFAULT; + tree[_indexer].lsum=tree[_indexer].rsum=tree[_indexer].sum=R-L+1; + if(L!=R) + { + int mid=(L+R)>>1; + build(L,mid,_indexer<<1); + build(mid+1,R,_indexer<<1|1); + } +} + +void update(int L,int R,int NewAttr,int _indexer=1) +{ + if(L==tree[_indexer].lt&&R==tree[_indexer].rt) + { + tree[_indexer].lsum=tree[_indexer].rsum=tree[_indexer].sum= + NewAttr==1 ? 0 : tree[_indexer].rt-tree[_indexer].lt+1 ; /// Same as R-L+1 + tree[_indexer].attr=NewAttr; + return; + } + + /// Push Down (updated) + if(tree[_indexer].attr!=-1) + { + /// Sync the Attribute to sub-tree + tree[_indexer<<1].attr=tree[_indexer<<1|1].attr=tree[_indexer].attr; + tree[_indexer].attr=-1; + tree[_indexer<<1].rsum=tree[_indexer<<1].lsum=tree[_indexer<<1].sum= tree[_indexer<<1].attr==1 ? 0 : tree[_indexer<<1].rt-tree[_indexer<<1].lt+1; + tree[_indexer<<1|1].rsum=tree[_indexer<<1|1].lsum=tree[_indexer<<1|1].sum= tree[_indexer<<1|1].attr==1 ? 0 : tree[_indexer<<1|1].rt-tree[_indexer<<1|1].lt+1; + } + + int mid=(tree[_indexer].lt+tree[_indexer].rt)>>1; + if(R<=mid) + { + update(L,R,NewAttr,_indexer<<1); + } + else if(L>mid) + { + update(L,R,NewAttr,_indexer<<1|1); + } + else + { + update(L,mid,NewAttr,_indexer<<1); + update(mid+1,R,NewAttr,_indexer<<1|1); + } + + /// Push Up (updated) + tree[_indexer].lsum=tree[_indexer<<1].lsum; /// left & left + tree[_indexer].rsum=tree[_indexer<<1|1].rsum; /// right & right + + if(tree[_indexer<<1].lsum == tree[_indexer<<1].rt-tree[_indexer].lt+1) + { + /// Father.LeftSum == RightSon.LeftSum + LeftSon.LeftSum + tree[_indexer].lsum+=tree[_indexer<<1|1].lsum; + } + + /// Why tree[_indexer].rsum but not tree[_indexer<<1|1].rsum ??? + if(tree[_indexer].rsum==tree[_indexer<<1|1].rt-tree[_indexer<<1|1].lt+1) + { + /// Father.RightSum == LeftSon.RightSum + RightSon.RightSum + tree[_indexer].rsum+=tree[_indexer<<1].rsum; + } + + tree[_indexer].sum=max(max(tree[_indexer<<1].sum,tree[_indexer<<1|1].sum),tree[_indexer<<1].rsum+tree[_indexer<<1|1].lsum); + + +} + +int query(int Val,int _indexer=1) +{ + if(tree[_indexer].lt==tree[_indexer].rt) + { + return tree[_indexer].lt; + } + /// Push Down (updated) + if(tree[_indexer].attr!=-1) + { + /// Sync the Attribute to sub-tree + tree[_indexer<<1].attr=tree[_indexer<<1|1].attr=tree[_indexer].attr; + tree[_indexer].attr=-1; + tree[_indexer<<1].rsum=tree[_indexer<<1].lsum=tree[_indexer<<1].sum= tree[_indexer<<1].attr==1 ? 0 : tree[_indexer<<1].rt-tree[_indexer<<1].lt+1; + tree[_indexer<<1|1].rsum=tree[_indexer<<1|1].lsum=tree[_indexer<<1|1].sum= tree[_indexer<<1|1].attr==1 ? 0 : tree[_indexer<<1|1].rt-tree[_indexer<<1|1].lt+1; + } + int Mid=(tree[_indexer].rt+tree[_indexer].lt)>>1; + /// Left + if(tree[_indexer<<1].sum>=Val) + { + return query(Val,_indexer<<1); + } + /// Both Left and Right + else if(tree[_indexer<<1].rsum+tree[_indexer<<1|1].lsum >= Val) + { + return Mid-tree[_indexer<<1].rsum+1; + } + else /// Right + { + return query(Val,_indexer<<1|1); + } +} + +}/// End of namespace AttributeMergeSegmentTree + +Ӷ(LCIS)߶(HDU 3308) ģ +/// ִ ߶ +namespace LCISSegmentTree +{ + +const int MAXN = 1000100; +const int MAXTREENODE = MAXN<<2; + + +int seq[MAXN]; + +struct node +{ + /// Be Sure That "BounderLen" always equal to "RightBounder - LeftBounder + 1" + /// And Bounder Never change in one single test. + int leftbounder,rightbounder,bounderlen; + int leftseqlen,rightseqlen,mergedseqlen; /// From HDU 3308 + int leftvalue,rightvalue; +}; + +node tree[MAXTREENODE]; + +/// _internal_v is a indexer of SegmentTree. It guides the procedure to the right node. + +void pushup(int _internal_v) +{ + /// Left == Left.Left + tree[_internal_v].leftseqlen=tree[_internal_v<<1].leftseqlen; + tree[_internal_v].leftvalue=tree[_internal_v<<1].leftvalue; + + /// Right == Right.Right + tree[_internal_v].rightseqlen=tree[_internal_v<<1|1].rightseqlen; + tree[_internal_v].rightvalue=tree[_internal_v<<1|1].rightvalue; + + /// Merged SeqLen is the max one of two sub-tree.MergedSeqLen + tree[_internal_v].mergedseqlen=max(tree[_internal_v<<1].mergedseqlen,tree[_internal_v<<1|1].mergedseqlen); + + /// If LeftSon.RightValue < RightSon.LeftValue, a longer Seq may exist. + if(tree[_internal_v<<1].rightvalue>1; + build(L,mid,_internal_v<<1); + build(mid+1,R,_internal_v<<1|1);/// x<<1 == x*2; x<<1|1 == x*2+1; (faster == slower) + + /// Push Up + pushup(_internal_v); +} + +void update(int Pos,int Val,int _internal_v=1)/// Update a position, _internal_v is 1 by default. +{ + /// Reach a clearly node with same LeftBounder and RightBounder + if(tree[_internal_v].leftbounder==tree[_internal_v].rightbounder) + { + tree[_internal_v].leftvalue=tree[_internal_v].rightvalue=Val; + return; + } + /// Calculate Mid + int mid=(tree[_internal_v].leftbounder+tree[_internal_v].rightbounder)>>1; + /// If in left then try update in left + if(Pos <= mid) + update(Pos,Val,_internal_v<<1); + else /// Else try update in right + update(Pos,Val,_internal_v<<1|1); + /// And then push it up ! + pushup(_internal_v); +} + +int query(int L,int R,int _internal_v=1) +{ + /// This Node ( and the segment which is under its control ) + /// is included in query area. + if(L<=tree[_internal_v].leftbounder && tree[_internal_v].rightbounder <= R) + { + return tree[_internal_v].mergedseqlen; + } + /// Calculate Mid + int mid=(tree[_internal_v].leftbounder+tree[_internal_v].rightbounder)>>1; + /// Answer saved in 'ans' + int ans=0; + + /// Query If Segment L~R has common area with ThisNode.LeftBounder~Mid + if(L<=mid) + { + ans=max(ans,query(L,R,_internal_v<<1)); + } + + /// Query If Segment L~R has common area with Mid+1 ~ ThisNode.RightBounder + if(mid +#include +#include +using namespace std; + +void getfill(string s,int* f) +{ + //memset(f,0,sizeof(f)); //ǰһĸõ + for(size_t i=1;i +#include +#include +#include +#include +#define INF 0x3f3f3f3f +using namespace std; +const int maxn = 10010; +struct node +{ + int lt,rt,v; +}; +node tree[maxn<<2]; + +/** ========== Conditional =========== */ +using ValueType = int; + +inline ValueType algo_delegate(ValueType a,ValueType b) +{ + return min(a,b); +} +/****************************************/ + +void build(int lt,int rt,int v) +{ + tree[v].lt = lt; + tree[v].rt = rt; + if(lt == rt) + { + scanf("%d",&tree[v].v); + return; + } + int mid = (lt + rt)>>1; + build(lt,mid,v<<1); + build(mid+1,rt,v<<1|1); + tree[v].v = algo_delegate(tree[v<<1].v,tree[v<<1|1].v); +} +void update(int p,int val,int v) +{ + if(tree[v].lt == tree[v].rt) + { + tree[v].v = val; + return; + } + if(p <= tree[v<<1].rt) update(p,val,v<<1); + if(p >= tree[v<<1|1].lt) update(p,val,v<<1|1); + tree[v].v = algo_delegate(tree[v<<1].v,tree[v<<1|1].v); +} +int query(int lt,int rt,int v) +{ + if(tree[v].lt >= lt && tree[v].rt <= rt) + return tree[v].v; + int a = INF,b = INF; + if(lt <= tree[v<<1].rt) a = query(lt,rt,v<<1); + if(rt >= tree[v<<1|1].lt) b = query(lt,rt,v<<1|1); + return algo_delegate(a,b); +} + + LCIS +/// LCIS  +namespace LCIS +{ + +const int MAXLEN_A = 500; +const int MAXLEN_B = 500; +int dp[MAXLEN_A+5][MAXLEN_B+5]; +int deal(const char* a,const char* b) +{ + int lena=strlen(a); + int lenb=strlen(b); + for(int i=1;i<=lenb;i++) + { + int k=0; + for(int j=1;j<=lena;j++) + { + dp[i][j]=dp[i-1][j];/// when b[i-1] != a[j-1] + if(b[i-1]>a[j-1]) k=max(k,dp[i-1][j]); + else if(b[i-1]==a[j-1]) dp[i][j]=k+1; + } + } + int ans=0; + for(int i=1;i<=lena;i++) ans=max(ans,dp[lenb][i]); + return ans; +} + +} +//End of namespace LCIS + + LCS (Updated On 20160819) +/// LCS  +namespace LCS +{ +const int MAXLEN_A = 512; +const int MAXLEN_B = 512; +int dp[MAXLEN_A][MAXLEN_B]; +int deal(const char* a,const char* b) +{ + int lena=strlen(a); + int lenb=strlen(b); + for(int i=0;i<=lenb;i++) + { + for(int j=0;j<=lena;j++) + { + if(i==0) dp[i][j]=0; + else if(j==0) dp[i][j]=0; + else if(b[i-1]==a[j-1]) + { + dp[i][j]=dp[i-1][j-1]+1; + } + else + { + dp[i][j]=max(dp[i-1][j],dp[i][j-1]); + } + } + } + return dp[lenb][lena]; +} +}//End of namespace LCS + +(LIS) õķ... lower_bound +// Longest Increasing Subsequence O(nlogn) +int b[N]; +int LIS(int a[], int n) { + int len = 1; b[0] = a[0]; + for (int i = 1; i < n; i++) { + b[a[i] > b[len - 1] ? len++ : lower_bound(b, b + len, a[i]) - b] = a[i]; //ǽΪ>=upper_bound + } + return len; +} + +Floyd㷨е֮̾룬ֻҪһ㵽̾ӦʹDijstra㷨 + +FloydLogic + +עm[f][t] Ϊ ftľ. DZߵʽͼʽҪ + +for(int k=1;k<=n;k++) + { + for(int f=1;f<=n;f++) + { + for(int t=1;t<=n;t++) + { + if(f==t||f==k||t==k) continue; + if(m[f][k]!=INF&&m[k][t]!=INF) + { + int total=m[f][k]+m[k][t]; + if(total0) + { + + if(b % 2 == 1) + ans = (ans * a) % c; + b = b/2; + a = (a * a) % c; + } + return ans; +} + +///Լɪ,n,m +int JosephusProblem_Solution4(int n, int m) +{ + if(n < 1 || m < 1) + return -1; + + vector f(n+1,0); + for(unsigned i = 2; i <= n; i++) + f[i] = (f[i-1] + m) % i; + + return f[n]; +} + +DPӶ,ӶO(N) + +ҪӶյ +int MaxSum(int n,int *a) +{ + int sum=NINF,b=0; + for(int i=0; i0) + { + b+=a[i]; + } + else + { + b=a[i]; + } + if(b>sum) + { + sum = b; + } + } + return sum; +} +ҪӶյ +typedef struct +{ + int result,start,ends; +}PACK; +PACK MaxSum(int N,int* a) +{ + int sum=-1; + int tmp=0; + int start=0; + int ends=0; + int tmpstart=0; + int tmpends=0; + for(int i=0;i0) + { + tmp+=a[i]; + tmpends=i; + } + else + { + tmp=a[i]; + tmpstart=i; + } + if(tmp>sum) + { + sum=tmp; + start=tmpstart; + ends=tmpends; + } + } + if(endssum) + { + sum = max; + } + + } + } + delete[] b; + return sum; +} + +ξ +int MaxSumSquare(int N,ARRAY& a) +{ + return MaxSumRect(N,N,a); +} + + +const int INF = 0x3f3f3f3f; +const int NINF = 0xc0c0c0c0; + +#include +#include +using namespace std; + +(GitHub: kiritow/OJ-Problems-Source) + + +namespace RMQ_ST +{ +const int MAXN=10000; +int f[MAXN][MAXN]; +int a[MAXN]; +int n; +void init() +{ + for(int i = 1;i<=n;i++) + { + f[i][0]=a[i]; + } + for(int j=1;(1< +struct str_hash { + size_t operator()(const string &str)const { + return __stl_hash_string(str.c_str()); + } +}; +//BKDR Hash Function +inline size_t BKDRHash(const char *str) { + size_t h = 0, seed = 131; //31 131 1313 13131 131313 etc.. + while (*str) { h = h * seed + (*str++); } + return h & 0x7FFFFFFF; +} +//ַhash +const int N = 20005, P = 31, D = 1000173169; +int n, pp[N] = {1}, hs[N]; char s[N]; +int get(int l, int r) { return ((hs[r] - (ll)hs[l - 1] * pp[r - l + 1]) % D + D) % D; } +int main() { + scanf("%d%s", &n, s + 1); + for (int i = 1; i <= n; i++) { pp[i] = pp[i - 1] * P % D; } + for (int i = 1; i <= n; i++) { hs[i] = ((ll)hs[i - 1] * P + s[i]) % D; } +} +//дhash_map +const int P = 13131; +char key[N][M]; +typedef struct Node { int id, val; } etype; +template struct hashmap { + vector hs[P]; + void init() { for (int i = 0; i < P; i++) { hs[i].clear(); } } + void insert(int id, int val) { + int h = Hash(key[id]) % P; hs[h].push_back((etype) {id, val}); + } + bool erase(char *buf) { + int h = Hash(buf) % P; + for (size_t i = 0; i < n; i++) { if (!strcmp(buf, key[hs[h][i].id])) { hs[h].erase(hs[h].begin() + i); return true; } } + return false; + } + int query(char *buf) { + int h = Hash(buf) % P; + for (size_t i = 0; i < n; i++) { if (!strcmp(buf, key[hs[h][i].id])) { return hs[h][i].val; } } + return false; + } +}; +hashmap mp; +//Manacher Ӵ +//ӴӦԭTеλ: l = (i - R[i]) / 2; r = (i + R[i]) / 2 - 2; +char s[N], tmp[N << 1]; +int dp[N << 1]; +void Manacher(char *s, int len) { + int l = 0, mx = 0, id = 0; tmp[l++] = '$'; tmp[l++] = '#'; + for (int i = 0; i < len; i++) { tmp[l++] = s[i]; tmp[l++] = '#'; } + tmp[l] = 0; + for (int i = 0; i < l; i++) { + dp[i] = mx > i ? min(dp[(id << 1) - i], mx - i) : 1; + while (tmp[i + dp[i]] == tmp[i - dp[i]]) { dp[i]++; } + if (i + dp[i] > mx) { mx = i + dp[i]; id = i; } + } +} +int main() { + while (~scanf("%s", s)) { + int len = strlen(s), mlen = (len << 1) + 2, mxlen = 0, mxpos = 0; + Manacher(s, len); + for (int i = 0; i < mlen; i++) { + if (mxlen < dp[i]) { mxlen = dp[i]; mxpos = i; } + } + printf("%d\n", mxlen - 1); //s.substr((mxpos - mxlen) >> 1, mxlen - 1); + } +} +//ַСʾ +int minString(char *s) { + int m = strlen(s), i, j, k; + char ss[m << 1]; strcpy(ss, s); strcpy(ss + m, s); + for (i = k = 0, j = 1; k < m && i < m && j < m;) { + for (k = 0; k < m && ss[i + k] == ss[j + k]; k++); + if (k < m) { + if (ss[i + k] > ss[j + k]) { i += k + 1; } //Ϊ< + else { j += k + 1; } + if (i == j) { j++; } + } + } + return min(i, j); +} +//strstr str1вstr2ĵһγ 򷵻NULL +char *strstr(const char *str1, const char *str2); +//KMP O(M + N) +//nxt[]ĺ壺x[i-nxt[i]...i-1]=x[0...nxt[i]-1] +//nxt[i]Ϊx[i-z...i-1]=x[0...z-1]zֵ(xƥ) +char x[N], y[N]; +int nxt[N]; +void getnxt(char *x, int m, int nxt[]) { + int i = 0, j = -1; nxt[0] = -1; + while (i < m) { + while (j != -1 && x[i] != x[j]) { j = nxt[j]; } + nxt[++i] = ++j; + } +} +//Ľ +void getnxt(char *x, int m, int nxt[]) { + int i = 0, j = -1; nxt[0] = -1; + while (i < m) { + while (j != -1 && x[i] != x[j]) { j = nxt[j]; } + if (x[++i] == x[++j]) { nxt[i] = nxt[j]; } + else { nxt[i] = j; } + } +} +//xyгֵĴ, ص +//xģʽ, y +int KMPCount(char *x, int m, char *y, int n, int nxt[]/*, int &longest, int &lp*/) { + int i = 0, j = 0, ans = 0; //longest = 0; lp = 0; + while (i < n) { + while (j != -1 && y[i] != x[j]) { j = nxt[j]; } + i++; j++; + //if (j > longest) { longest = j; lp = i - j; } + if (j >= m) { j = nxt[j]; ans++; } + } + return ans; +} +//չKMP +//nxt[i]:x[i...m-1]x[0...m-1]ǰ׺ +//ext[i]:y[i...n-1]x[0...m-1]ǰ׺ +int nxt[N], ext[N]; +void getnxt(char *x, int m, int nxt[]) { + int i = 2, j = 0, k = 1; + while (j + 1 < m && x[j] == x[j + 1]) { j++; } + nxt[0] = m; nxt[1] = j; + for (; i < m; i++) { + int p = nxt[k] + k - 1, l = nxt[i - k]; + if (i + l < p + 1) { nxt[i] = l; } + else { + j = max(0, p - i + 1); + while (i + j < m && x[i + j] == x[j]) { j++; } + nxt[i] = j; k = i; + } + } +} +void getext(char *x, int m, char *y, int n, int nxt[], int ext[]) { + getnxt(x, m); + int i = 1, j = 0, k = 0; + while (j < n && j < m && x[j] == y[j]) { j++; } + ext[0] = j; + for (; i < n; i++) { + int p = ext[k] + k - 1, l = nxt[i - k]; + if (i + l < p + 1) { ext[i] = l; } + else { + j = max(0, p - i + 1); + while (i + j < n && j < m && y[i + j] == x[j]) { j++; } + ext[i] = j; k = i; + } + } +} +//Sunday +int Sunday(char *x, int m, char *y, int n) { + int nxt[26] = {0}; + for (int j = 0; j < 26; j++) { nxt[j] = m + 1; } + for (int j = 0; j < m; j++) { nxt[x[j] - 'a'] = m - j; } + for (int pos = 0, i, j; pos <= n - m;) { + for (i = pos, j = 0; j < m; i++, j++) { + if (y[i] != x[j]) { pos += nxt[y[pos + m] - 'a']; break; } + } + if (j == m) { return pos; } + } + return -1; +} +//Rabin-Karp +#define UNSIGNED(x) ((unsigned char)x) +const int d = 257; +int hashMatch(char *s, int m, char *p, int n) { + if (m > n || m == 0 || n == 0) { return -1; } + //svΪsӴhash, pvΪphash, baseΪdm-1η + unsigned sv = UNSIGNED(s[0]), pv = UNSIGNED(p[0]), base = 1; + int i, j; + //ʼsv, pv, base + for (i = 1; i < m; i++) { + pv = pv * d + UNSIGNED(p[i]); + sv = sv * d + UNSIGNED(s[i]); + base *= d; + } + i = m - 1; + do { + if (!(sv ^ pv)) { + for (j = 0; j < m && s[i - m + 1 + j] == p[j]; j++); + if (j == m) { return i - m + 1; } + } + if (++i >= n) { break; } + //O(1)ʱڸsv, sv + UNSIGNED(s[i - m]) * (~base + 1)ȼsv - UNSIGNED(s[i - m]) * base + sv = (sv + UNSIGNED(s[i - m]) * (~base + 1)) * d + UNSIGNED(s[i]); + } while (i < n); + return -1; +} +//Trie +//ʵ +struct Trie { + int nxt[N * 20][26], val[N * 20], root, tot; + void init() { memset(nxt, 0, sizeof(nxt)); memset(val, 0, sizeof(val)); root = tot = 1; } + void insert(char *buf, int id) { + int len = strlen(buf), now = root; + for (int i = 0, c; i < len; i++) { + if (!nxt[now][c = buf[i] - 'a']) { nxt[now][c] = ++tot; } + now = nxt[now][c]; + } + val[now] = id; + } + int query(char *buf) { + int len = strlen(buf), now = root; + for (int i = 0, c; i < len; i++) { + if (!nxt[now][c = buf[i] - 'a']) { return -1; } + now = nxt[now][c]; + } + return val[now]; + } +} tr; +//ָʵ +struct Node { Node *nxt[26]; int val; }; +struct Trie { + Node *root; + void init() { erase(root); root = new Node(); } + void insert(char *buf, int id) { + int len = strlen(buf); Node *now = root; + for (int i = 0, c; i < len; i++) { + if (!now->nxt[c = buf[i] - 'a']) { now->nxt[c] = new Node(); } + now = now->nxt[c]; + } + now->val = id; + } + void erase(Node *p) { + if (p) { for (int i = 0; i < 26; i++) { erase(p->nxt[i]); } delete p; } + } + int query(char *buf) { + int len = strlen(buf); Node *now = root; + for (int i = 0, c; i < len; i++) { + if (!now->nxt[c = buf[i] - 'a']) { return -1; } + now = now->nxt[c]; + } + return now->val; + } +} tr; +//ACԶ +struct AC { + int nxt[N * 20][26], fail[N * 20], val[N * 20], root, tot; + void init() { memset(nxt, 0, sizeof(nxt)); memset(val, 0, sizeof(val)); root = tot = 1; } + void insert(char *buf, int id) { + int len = strlen(buf), now = root; + for (int i = 0, c; i < len; i++) { + if (!nxt[now][c = buf[i] - 'a']) { nxt[now][c] = ++tot; } + now = nxt[now][c]; + } + val[now] = id; + } + void build() { + queue que; fail[root] = root; + for (int i = 0; i < 26; i++) { + if (!nxt[root][i]) { nxt[root][i] = root; } + else { fail[nxt[root][i]] = root; que.push(nxt[root][i]); } + } + while (!que.empty()) { + int now = que.front(); que.pop(); + for (int i = 0; i < 26; i++) { + if (!nxt[now][i]) { nxt[now][i] = nxt[fail[now]][i]; } + else { fail[nxt[now][i]] = nxt[fail[now]][i]; que.push(nxt[now][i]); } + } + } + } + int query(char *buf) { + int len = strlen(buf), now = root, res = 0; + for (int i = 0, c; i < len; i++) { + for (int tmp = now = nxt[now][c = buf[i] - 'a']; tmp != root; tmp = fail[tmp]) { + res += val[tmp]; //val[tmp] = 0; + } + } + return res; + } +} ac; +//׺ +//n +//mַС +//s[0..n - 1]ַ +//sa[1..n]ֵ i Сĸ׺ +//rnk[0..n - 1]׺ i +//height[i]lcp(sa[i], sa[i - 1]) +int rnk[N], sa[N], height[N], tmp[N], cnt[N]; +void SA(char *s, int n, int m) { + int i, j, k; n++; + memset(rnk, 0, sizeof(rnk)); memset(sa, 0, sizeof(sa)); memset(height, 0, sizeof(height)); + memset(tmp, 0, sizeof(tmp)); memset(cnt, 0, sizeof(cnt)); + for (i = 0; i < n; i++) { cnt[rnk[i] = s[i]]++; } + for (i = 1; i < m; i++) { cnt[i] += cnt[i - 1]; } + for (i = 0; i < n; i++) { sa[--cnt[rnk[i]]] = i; } + for (k = 1; k <= n; k <<= 1) { + for (i = 0; i < n; i++) { + j = sa[i] - k; + if (j < 0) { j += n; } + tmp[cnt[rnk[j]]++] = j; + } + sa[tmp[cnt[0] = 0]] = j = 0; + for (i = 1; i < n; i++) { + if (rnk[tmp[i]] != rnk[tmp[i - 1]] || rnk[tmp[i] + k] != rnk[tmp[i - 1] + k]) { cnt[++j] = i; } + sa[tmp[i]] = j; + } + memcpy(rnk, sa, n * sizeof(int)); + memcpy(sa, tmp, n * sizeof(int)); + if (j >= n - 1) { break; } + } + for (j = rnk[height[i = k = 0] = 0]; i < n - 1; i++, k++) { + while (k >= 0 && s[i] != s[sa[j - 1] + k]) { height[j] = k--, j = rnk[sa[j] + 1]; } + } +} +//׺Զ +const int N = 1000005; +const int N_CHAR = 26; +struct SuffixAutomaton { + struct Node { Node *fail, *next[N_CHAR]; int val, right; }; + Node mempool[N << 1]; int n_node; + Node *new_node(int v) { + Node *p = &mempool[n_node++]; memset(p->next, 0, sizeof(p->next)); + p->fail = 0; p->right = 0; p->val = v; return p; + } + Node *root, *last; + SuffixAutomaton() { clear(); } + void clear() { root = last = new_node(n_node = 0); } + void add(int c) { + Node *p = last, *np = new_node(p->val + 1); + while (p && !p->next[c]) { p->next[c] = np; p = p->fail; } + if (!p) { np->fail = root; } + else { + Node *q = p->next[c]; + if (p->val + 1 == q->val) { np->fail = q; } + else { + Node *nq = new_node(p->val + 1); + for (int i = 0; i < N_CHAR; i++) { nq->next[i] = q->next[i]; } + nq->fail = q->fail; q->fail = np->fail = nq; + while (p && p->next[c] == q) { p->next[c] = nq; p = p->fail; } + } + } + last = np; np->right = 1; + } + Node *go(const char *s) { + Node *p = root; int cL = 0; //sƥij + for (int i = 0; s[i]; i++) { + int c = s[i] - 'a'; + if (p->next[c]) { p = p->next[c], ++cL; } + else { + while (p && !p->next[c]) { p = p->fail; } + if (!p) { cL = 0; p = root; } + else { cL = p->val + 1; p = p->next[c]; } + } + } + return p; + } + int d[N << 1]; Node *b[N << 1]; + void toposort() { + for (int i = 0; i <= n_node; i++) { d[i] = 0; } + int mx_val = 0; + for (int i = 0; i < n_node; i++) { mx_val = max(mx_val, mempool[i].val); d[mempool[i].val]++; } + for (int i = 1; i <= mx_val; i++) { d[i] += d[i - 1]; } + for (int i = 0; i < n_node; i++) { b[--d[mempool[i].val]] = &mempool[i]; } + } + void updateright() { + toposort(); + for (int i = n_node - 1; i; i--) { b[i]->fail->right += b[i]->right; } + } +} sa; +// +struct PalindromicTree { + int nxt[N][26]; //ָĴΪǰ˼ͬһַ + int fail[N]; //ʾʧתСڸôԸýڵʾĴһַβĴʾĽڵ + int cnt[N]; //ʾڵʾıʲͬĴĸ(ʱIJȫ, countһԺȷ) + int num[N]; //ʾԽڵʾĴҶ˵ΪĴβĻĴ + int len[N]; //ʾڵʾĻĴ + int S[N]; //ʾiӵַ(S[0] = -1(һڴвֵַ)) + int last; //ָһĸγɵĴʾĽڵ + int n; //ʾӵַ + int tot; //ʾڵ + int newnode(int l) { len[tot] = l; return tot++; } + void init() { + memset(nxt, 0, sizeof(nxt)); memset(cnt, 0, sizeof(cnt)); memset(len, 0, sizeof(len)); + newnode(0); newnode(-1); tot = last = n = 0; S[n] = -1; fail[0] = 1; + } + int getfail(int x) { //ʧһ + while (S[n - len[x] - 1] != S[n]) { x = fail[x]; } + return x; + } + void add(int c) { + c -= 'a'; S[++n] = c; + int cur = getfail(last); //ͨһĴĴƥλ + if (!nxt[cur][c]) { //Ĵûгֹ, ˵һµıʲͬĻĴ + int now = newnode(len[cur] + 2); //½ڵ + fail[now] = nxt[getfail(fail[cur])][c]; //ACԶһfailָ, Աʧת + nxt[cur][c] = now; num[now] = num[fail[now]] + 1; + } + cnt[last = nxt[cur][c]]++; + } + void count() { + for (int i = tot - 1; i >= 0; i--) { cnt[fail[i]] += cnt[i]; } + //ۼӶӵcnt, Ϊfail[v] = u, uһvӻĴ + } +} pat; diff --git a/.ACM-Templates/TXTs/并查集.txt b/.ACM-Templates/TXTs/并查集.txt new file mode 100644 index 0000000..5c24a06 --- /dev/null +++ b/.ACM-Templates/TXTs/并查集.txt @@ -0,0 +1,21 @@ +//鼯 + ·ѹ O(logn) +int fa[N]; +void init(int n) { for (int i = 0; i <= n; i++) { fa[i] = i; } } +int findfa(int n) { return n == fa[n] ? n : fa[n] = findfa(fa[n]); } +inline void unite(int x, int y) { + x = findfa(x); y = findfa(y); + if (x != y) { fa[y] = x; } +} +//鼯 + ·ѹ + ʽϲ O(alpha(n)) +int fa[N], rnk[N]; +void init(int n) { for (int i = 0; i <= n; i++) { fa[i] = i; rnk[i] = 0; } } +int findfa(int n) { return n == fa[n] ? n : fa[n] = findfa(fa[n]); } +inline void unite(int x, int y) { + x = findfa(x); y = findfa(y); + if (x != y) { + if (rnk[x] > rnk[y]) { fa[y] = x; } + else { fa[x] = y; if (rnk[x] == rnk[y]) { rnk[y]++; } } + } +} +//·ѹ +int findfa(int n) { while (fa[n] != n) { fa[n] = fa[fa[n]]; n = fa[n]; } return n; } diff --git a/.ACM-Templates/TXTs/应用.txt b/.ACM-Templates/TXTs/应用.txt new file mode 100644 index 0000000..283d968 --- /dev/null +++ b/.ACM-Templates/TXTs/应用.txt @@ -0,0 +1,210 @@ +//Joseph O(n) +int Joseph(int n, int m, int s) { + int ret = s - 1; + for (int i = 2; i <= n; i++) { ret = (ret + m) % i; } + return ret + 1; +} +//O(logn) 0 <= k < n +int Joseph(int n, int m, int k) { + if (m == 1) { return n - 1; } + for (k = k * m + m - 1; k >= n; k = k - n + (k - n) / (m - 1)); + return k; +} +//չ fac[]Ϊ׳ 0 <= ans +ll Cantor(char *s) { + ll ans = 0; + for (int i = 0, len = strlen(s); i < len; i++) { + int cnt = 0; + for (int j = i + 1; j < len; j++) { if (s[j] < s[i]) { cnt++; } } + ans += cnt * fac[len - i - 1]; + } + return ans; +} +//չ 1 <= k <= n! +vector revCantor(ll n, ll k) { + vector v, ret; k--; + for (int i = 1; i <= n; i++) { v.push_back(i); } + for (int i = n; i >= 1; i--) { + ll t = k / fac[i - 1]; k %= fac[i - 1]; + sort(v.begin(), v.end()); + ret.push_back(v[t]); v.erase(v.begin() + t); + } + return ret; +} +//ȫΪidӾ +//ջ O(nm) +int n, m, a[N][N], h[N]; +int solve(int id) { + int ans = 0; + memset(h, 0, sizeof(h)); + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { h[j] = a[i][j] == id ? h[j] + 1 : 0; } + stack st; st.push(0); + for (int j = 1; j <= m + 1; j++) { + while (h[j] < h[st.top()]) { + int t = h[st.top()]; st.pop(); + int w = j - st.top() - 1; + ans = max(ans, t * w); + } + st.push(j); + } + } + return ans; +} +//dp ߷ O(nm) +int n, m, a[N][N], l[N], r[N], h[N]; +int solve(int id) { + int ans = 0; + for (int i = 1; i <= m; i++) { l[i] = 1; r[i] = m; h[i] = 0; } + for (int i = 1; i <= n; i++) { + for (int j = 1, mxl = 1; j <= m; j++) { + if (a[i][j] == id) { h[j]++; l[j] = max(l[j], mxl); } + else { h[j] = 0; l[j] = 1; r[j] = m; mxl = j + 1; } + } + for (int j = m, mxr = m; j >= 1; j--) { + if (a[i][j] == id) { r[j] = min(r[j], mxr); ans = max(ans, (r[j] - l[j] + 1) * h[j]); } + else { mxr = j - 1; } + } + } + return ans; +} +//ǰ + +void getPost(char *pre, char *in, int len) { + if (len == 0) { return; } + int root = 0; + for (; root < len && in[root] != *pre; root++); + getPost(pre + 1, in, root); + getPost(pre + root + 1, in + root + 1, len - root - 1); + putchar(*pre); +} +//1n֮1ĸ +ll countOne(ll n) { + ll ret = 0; + for (ll m = 1; m <= n; m *= 10) { + ll a = n / m, b = n % m; + ret += (a + 8) / 10 * m + (a % 10 == 1) * (b + 1); + } + return ret; +} +//1nֵλ͵ĺ λDP +char t[N]; +ll dp[N][N][N]; +ll countDigit(char *s) { + ll ret = 0; + for (int i = 1, n = strlen(s); i <= n; i++) { t[i] = s[i - 1] - '0'; } + for (int i = 0; i <= t[1]; i++) { dp[1][i][i == t[1]] = 1; } + for (int i = 1; i < n; i++) { + for (int j = 1; j <= 900; j++) { + if (dp[i][j][0]) { + for (int k = 0; k <= 9; k++) { dp[i + 1][j + k][0] += dp[i][j][0]; dp[i + 1][j + k][0] %= M; } + } + if (dp[i][j][1]) { + for (int k = 0; k <= t[i + 1]; k++) { dp[i + 1][j + k][k == t[i + 1]] += dp[i][j][1]; dp[i + 1][j + k][k == t[i + 1]] %= M; } + } + } + } + for (int j = 1; j <= 900; j++) { ret += dp[n][j][0] * dp[n][j][1] % M; ret %= M; } + return ret; +} +//hash +int hs[N], P[N]; //һЩ +void dfs(int u, int p) { + vector t; t.push_back(1); + for (int i = 0; i < (int)e[u].size(); i++) { + int v = e[u][i]; + if (v == p) { continue; } + dfs(v, u); t.push_back(hs[v]); + } + sort(t.begin(), t.end()); hs[u] = 0; + for (int i = 0; i < (int)t.size(); i++) { hs[u] += t[i] * P[i]; } +} +for (int j = 1; j <= n; j++) { + dfs(j, 0); //cout << j << ' ' << hs[j] << endl; +} +sort(hs[i] + 1, hs[i] + n + 1); // +//ַ O(n^1.5) +int n, f[777] = {0, 1, 2, 5, 7}, g[N] = {1}; +int main() { + for (int i = 5; i < 777; i++) { f[i] = 3 + 2 * f[i - 2] - f[i - 4]; } + while (~scanf("%d", &n)) { + for (int i = 1; i <= n; i++) { + for (int j = 1; f[j] <= i; j++) { + if ((j + 1) >> 1 & 1) { g[i] = (g[i] + g[i - f[j]]) % M; } + else { g[i] = ((g[i] - g[i - f[j]]) % M + M) % M; } + } + } + printf("%d\n", g[n]); + } +} +//gcdԤ +int l[N], v[N]; +void calGCD { + for (int i = 1, j; i <= n; i++) { + for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) { + v[j] = __gcd(v[j], a[i]); + while (l[j] > 1 && __gcd(a[i], v[l[j] - 1]) == __gcd(a[i], v[j])) { l[j] = l[l[j] - 1]; } + //[l[j]...j, i]ڵֵgcdΪv[j] + } + } +} +//СתΪ +//СתΪ, ѭ()ʾ +void work(char str[]) { + int len = strlen(str), cnt1 = 0, cnt2 = 0; + ll a = 0, b = 0; bool flag = false; + for (int i = 2; i < len; i++) { + if (str[i] == '(') { break; } + a = a * 10 + str[i] - '0'; cnt1++; + } + for (int i = 2; i < len; i++) { + if (str[i] == '(' || str[i] == ')') { flag = true; continue; } + b = b * 10 + str[i] - '0'; cnt2++; + } + ll p = b - a, q = 0; cnt2 -= cnt1; + if (!flag) { p = b; q = 1; cnt2 = 0; } + for (int i = 0; i < cnt2; i++) { q = q * 10 + 9; } + for (int i = 0; i < cnt1; i++) { q = q * 10; } + ll g = gcd(p, q); + printf("%I64d/%I64d\n", p / g, q / g); +} +//תΪС +//: a / b(0 < a < b(a, b) = 1)ܱʾɴѭСijҪ(b, 10) = 1 +//: a / b, 0 < a < b, (a, b) = 1, b = (2 ^ ) * (5 ^ ) * b1, (b1, 10) = 1, +// b11²ȫΪ㣬a / bԱʾΪѭС䲻ѭλΪu = max(, ) +void work(int n) { + bool flag = false; + int ans[N] = { 0 }, f[N] = { 0, 1 }, k = 1, cnt = 0; + if (n < 0) { n = -n; flag = 1; } + while (k && n != 1) { + k *= 10; ans[cnt++] = k / n; k %= n; + if (f[k]) { break; } + f[k] = 1; + } + if (flag) { printf("-"); } + if (n == 1) { puts("1"); } + else { + printf("0."); + for (int i = 0; i < cnt; i++) { printf("%d", ans[i]); } + puts(""); + } +} +//ˮɻ A023052 Powerful numbers(3): numbers n that are the sum of some fixed power of their digits. +int Nar[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 4150, 4151, 8208, 9474, 54748, 92727, 93084, + 194979, 548834, 1741725, 4210818, 9800817, 9926315, 14459929, 24678050, 24678051, 88593477 + }; +// A000396 Perfect numbers n: n is equal to the sum of the proper divisors of n. +string str[] = { + "6", + "28", + "496", + "8128", + "33550336", + "8589869056", + "137438691328", + "2305843008139952128", + "2658455991569831744654692615953842176", + "191561942608236107294793378084303638130997321548169216", + "13164036458569648337239753460458722910223472318386943117783728128", + "14474011154664524427946373126085988481573677491474835889066354349131199152128", + "23562723457267347065789548996709904988477547858392600710143027597506337283178622239730365539602600561360255566462503270175052892578043215543382498428777152427010394496918664028644534128033831439790236838624033171435922356643219703101720713163527487298747400647801939587165936401087419375649057918549492160555646976" +}; diff --git a/.ACM-Templates/TXTs/排序查找.txt b/.ACM-Templates/TXTs/排序查找.txt new file mode 100644 index 0000000..a408607 --- /dev/null +++ b/.ACM-Templates/TXTs/排序查找.txt @@ -0,0 +1,41 @@ +// ֵ +const double EPS = 1e-9; +double TS(double l, double r) { + while (r - l > EPS) { + double mid1 = l + (r - l) / 3.0, mid2 = r - (r - l) / 3.0; + if (calc(mid1) > calc(mid2)) { r = mid2; } + else { l = mid1; } + } + return l; +} +//鲢 +ll cnt; +void mergeSort(int a[], int l, int r) { + if (l >= r) { return; } + int mid = (l + r) >> 1; + mergeSort(a, l, mid); + mergeSort(a, mid + 1, r); + vector res(r - l + 1); + int i = l, j = mid + 1, k = 0; + while (i <= mid && j <= r) { + if (a[i] > a[j]) { res[k++] = a[j++]; cnt += mid + 1 - i; } + else { res[k++] = a[i++]; } + } + while (i <= mid) { res[k++] = a[i++]; } + while (j <= r) { res[k++] = a[j++]; } + for (k = l; k <= r; k++) { a[k] = res[k - l]; } +} +// +void quickSort(int a[], int l, int r) { + if (l >= r) { return; } + int i = l, j = r, v = a[l]; + while (i < j) { + while (i < j && a[j] >= v) { j--; } + a[i] = a[j]; + while (i < j && a[i] <= v) { i++; } + a[j] = a[i]; + } + a[i] = v; + quickSort(a, l, i - 1); + quickSort(a, i + 1, r); +} diff --git a/.ACM-Templates/TXTs/数学数论.txt b/.ACM-Templates/TXTs/数学数论.txt new file mode 100644 index 0000000..c659c47 --- /dev/null +++ b/.ACM-Templates/TXTs/数学数论.txt @@ -0,0 +1,634 @@ +//快速幂 +ll powMod(ll a, ll b, ll m) { + ll r = 1; + for (a %= m; b; b >>= 1) { if (b & 1) { r = r * a % m; } a = a * a % m; } + return r; +} +//素数筛 +//Eratosthenes O(nloglogn) +const int N = 10000000; //~110ms +bitset isprime; +void getPrime() { + isprime.set(); isprime[0] = isprime[1] = false; + for (int i = 2; i < N; i++) { + if (isprime[i]) { + for (ll j = (ll)i * i; j < N; j += i) { isprime[j] = false; } + } + } +} +//Euler O(n) prime[0]为个数 +const int N = 10000000; //~110ms +int prime[N]; //3711111 for [2, 10^9) +void getPrime() { + for (int i = 2; i < N; i++) { + if (!prime[i]) { prime[++prime[0]] = i; } + for (int j = 1; j <= prime[0] && prime[j] * i < N; j++) { + prime[prime[j] * i] = 1; + if (i % prime[j] == 0) { break; } + } + } +} +//Euler O(n) +const int N = 10000000; //~95ms +int prime[N >> 3]; bitset isprime; +void getPrime() { + isprime.set(); isprime[0] = isprime[1] = false; + for (int i = 2; i < N; i++) { + if (isprime[i]) { prime[++prime[0]] = i; } + for (int j = 1; j <= prime[0] && prime[j] * i < N; j++) { + isprime[prime[j] * i] = false; + if (i % prime[j] == 0) { break; } + } + } +} +//[a, b]区间内素数个数 +bitset isprime, isprimesmall; +ll segPrime(ll a, ll b) { + ll ret = 0; isprime.set(); isprimesmall.set(); + for (int i = 2; (ll)i * i <= b; i++) { + if (isprimesmall[i]) { + for (ll j = (ll)i * i; (ll)j * j <= b; j += i) { isprimesmall[j] = false; } + for (ll j = max(2ll, (a + i - 1) / i)) * i; j <= b; j += i) { isprime[j - a] = false; } + } + } + for (ll i = 0; i <= r - l; i++) { ret += isprime[i]; } + return ret; +} +//分解质因数 +ll factor[100], facCnt; +void getFactors(ll x) { + facCnt = 0; + for (int i = 2, xx = sqrt(x + 0.5); i <= xx; i++) { + if (x % i == 0) { + factor[facCnt++] = i; + while (x % i == 0) { x /= i; } + } + } + if (x != 1) { factor[facCnt++] = x; } +} +//分解质因数及个数 预处理素数表 +ll factor[100][2], facCnt; +void getFactors(ll x) { + facCnt = 0; + for (int i = 1; prime[i] <= x / prime[i]; i++) { + factor[facCnt][1] = 0; + if (x % prime[i] == 0) { + factor[facCnt][0] = prime[i]; + while (x % prime[i] == 0) { factor[facCnt][1]++; x /= prime[i]; } + facCnt++; + } + } + if (x != 1) { factor[facCnt][0] = x; factor[facCnt++][1] = 1; } +} +//Miller-Rabin素性测试 素数返回true 错误(伪素数)概率为1/4^Times +const int Times = 7; +int WIT[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}; //7 bases for n < 2^64 +ll mulMod(ll a, ll b, ll m) { + ll r = 0; + for (a %= m, b %= m; b; b >>= 1) { if (b & 1) { r = (r + a) % m; } a = (a << 1) % m; } + return r; +} +ll powMod(ll a, ll b, ll m) { + ll r = 1; + for (a %= m; b; b >>= 1) { if (b & 1) { r = mulMod(r, a, m); } a = mulMod(a, a, m); } + return r; +} +bool Miller_Rabin(ll n) { + if (n == 2) { return true; } + if (n < 2 || (n & 1) == 0) { return false; } + ll m = n - 1; int k = 0; + while ((m & 1) == 0) { k++; m >>= 1; } + for (int i = 0; i < Times; i++) { + ll a = WIT[i], x = powMod(a, m, n), y = 0; + //ll a = rand() % (n - 1) + 1; + for (int j = 0; j < k; j++, x = y) { + y = mulMod(x, x, n); + if (y == 1 && x != 1 && x != n - 1) { return false; } + } + if (y != 1) { return false; } + } + return true; +} +//pollard rho质因素分解 +//对n进行素因子分解, 存入factor, k设置为107左右即可 +ll factor[100], facCnt; //质因素分解结果(无序) +ll pollard_rho(ll x, ll c) { + ll i = 1, k = 2, x0 = rand() % (x - 1) + 1, y = x0; + while (true) { + x0 = (mulMod(x0, x0, x) + c) % x; + ll d = llabs(__gcd(y - x0, x)); + if (d != 1 && d != x) { return d; } + if (y == x0) { return x; } + if (++i == k) { y = x0; k <<= 1; } + } +} +void findfac(ll n, int k = 107) { + if (n == 1) { return; } + if (Miller_Rabin(n)) { factor[facCnt++] = n; return; } + ll p = n; int c = k; + while (p >= n) { p = pollard_rho(p, c--); } //k值变化, 防止死循环 + findfac(p, k); findfac(n / p, k); +} +//求单个数的欧拉函数 +ll eular(ll n) { + ll ret = 1; + while ((n & 1) == 0) { n >>= 1; ret <<= 1; } + for (ll i = 3; i * i <= n; i += 2) { + if (n % i == 0) { n /= i; ret *= i - 1; while (n % i == 0) { n /= i; t *= i; } } + } + return n > 1 ? ret * (n - 1) : ret; +} +//欧拉函数筛 O(nloglogn) +const int N = 10000000; //~400ms +int phi[N] = {0, 1}; +void getPhi() { + for (int i = 2; i < N; i++) { + if (!phi[i]) { + for (int j = i; j < N; j += i) { + if (!phi[j]) { phi[j] = j; } phi[j] -= phi[j] / i; + } + } + } +} +//素数 + 欧拉函数筛 O(n) +const int N = 10000000; //~150ms +int prime[N >> 3], phi[N] = {0, 1}; bitset isprime; +void getPrimePhi() { + isprime.set(); isprime[0] = isprime[1] = false; + for (int i = 2; i < N; i++) { + if (isprime[i]) { prime[++prime[0]] = i; phi[i] = i - 1; } + for (int j = 1, k; j <= prime[0] && prime[j] * i < N; j++) { + isprime[k = prime[j] * i] = false; + if (i % prime[j] == 0) { phi[k] = phi[i] * prime[j]; break; } + phi[k] = phi[i] * (prime[j] - 1); + } + } +} +//素数 + 莫比乌斯函数筛 O(n) +const int N = 10000000; //150ms +int prime[N >> 3], miu[N] = {0, 1}; bitset isprime; +void getPrimeMiu() { + isprime.set(); isprime[0] = isprime[1] = false; + for (int i = 2; i < N; i++) { + if (isprime[i]) { prime[++prime[0]] = i; miu[i] = -1; } + for (int j = 1, k; j <= prime[0] && prime[j] * i < N; j++) { + isprime[k = prime[j] * i] = false; + if (i % prime[j] == 0) { miu[k] = 0; break; } + miu[k] = -miu[i]; + } + } +} +//素数 + 欧拉函数 + 莫比乌斯函数筛 O(n) +const int N = 10000000; //~230ms +int prime[N >> 3], phi[N] = {0, 1}, miu[N] = {0, 1}; bitset isnprime; +void getPrimePhiMiu() { + for (int i = 2; i < N; i++) { + if (!isnprime[i]) { prime[++prime[0]] = i; phi[i] = i - 1; miu[i] = -1; } + for (int j = 1, k; j <= prime[0] && prime[j] * i < N; j++) { + isnprime[k = prime[j] * i] = true; + if (i % prime[j] == 0) { phi[k] = phi[i] * prime[j]; miu[k] = 0; break; } + phi[k] = phi[i] * (prime[j] - 1); miu[k] = -miu[i]; + } + } +} +//素数 + 约数个数筛 O(n) +const int N = 10000000; //~200ms +bitset isprime; +int prime[N >> 3], faccnt[N] = {0, 1}, d[N]; //d[i]表示i的最小质因子的幂次 +void getPrimeFaccnt() { + isprime.set(); isprime[0] = isprime[1] = false; + for (int i = 2; i < N; i++) { + if (isprime[i]) { prime[++prime[0]] = i; faccnt[i] = 2; d[i] = 1; } + for (int j = 1, k; j <= prime[0] && prime[j] * i < N; j++) { + isprime[k = prime[j] * i] = false; + if (i % prime[j] == 0) { + faccnt[k] = faccnt[i] / (d[i] + 1) * (d[i] + 2); d[k] = d[i] + 1; break; + } + faccnt[k] = faccnt[i] << 1; d[k] = 1; + } + } +} +//A^B的约数之和为: +//sum = [1+p1+p1^2+...+p1^(a1*B)]*...*[1+pn+pn^2+...+pn^(an*B)]. +//等比数列求和 1+a+a^2+...+a^b +ll sumPow(ll a, ll b, ll m) { + ll r = 1; a %= m; + for (ll t = 1; b; b >>= 1) { + if (b & 1) { r = (r * a + t) % m; } + t = t * (a + 1) % m; + a = a * a % m; + } + return r; +} +//求逆元(ax = 1(mod m)的x值) +//扩展欧几里得(求ax + by = gcd(a, b)的解), 求出的x为a对b的模逆元 +ll exgcd(ll a, ll b, ll &x, ll &y) { + if (b == 0) { x = 1; y = 0; return a; } + ll d = exgcd(b, a % b, y, x); y -= a / b * x; return d; +} +//解不定方程ax + by = c 求得的只是其中一组解 +//对于不定整数方程ax + by = c, 若c mod gcd(a, b) = 0, 则该方程存在整数解, 否则不存在整数解 +//在找到ax + by = gcd(a, b)的一组解x0, y0后,可得到ax + by = c的一组解x1 = x0 * (c / gcd(a, b)), y1 = y0 * (c / gcd(a,b)) +//ax + by = c的其他整数解满足: +//x = x1 + b / gcd(a, b) * t, y = y1 - a / gcd(a, b) * t(其中t为任意整数) +//求ax + by = c的一组解 +bool linear_equation(int a, int b, int c, int &x, int &y) { + int d = exgcd(a, b, x, y); + if (c % d) { return false; } + int k = c / d; x *= k; y *= k; return true; +} +//求ax = b (mod p)循环节内的所有解 +ll ans[N], cnt; +bool linear_equation(ll a, ll b, ll p) { + ll x, y, d = exgcd(a, p, x, y); cnt = 0; + if (b % d) { return false; } + x = (x % p + p) % p; + ans[++cnt] = x * (b / d) % (p / d); + for (int i = 1; i < d; i++) { ans[++cnt] = (ans[1] + i * p / d) % n; } + return true; +} +//线性预处理逆元 +ll Inv[N] = {1, 1}; +void getInv(int m) { + for (ll i = 2; i < m; i++) { Inv[i] = (m - m / i) * Inv[m % i] % m; } +} +//扩展欧几里得求逆元 +ll modReverse(ll a, ll m) { + ll x, y, d = exgcd(a, m, x, y); + if (d == 1) { return (x % m + m) % m; } else { return -1; } +} +//费马小定理, m为素数, a与m互质 +ll inv(ll a, ll m) { return powMod(a, m - 2, m); } +//只能求0 < a < m的情况,a和m互质 +ll inv(ll a, ll m) { + if (a == 1) { return 1; } + return inv(m % a, m) * (m - m / a) % m; +} +//中国剩余定理 求模线性方程组x = a[i] (mod m[i]) m[i]可以不互质 +//[1, n]内解的个数为(n - x) / m1 + (x != 0) +bool merge(ll a1, ll m1, ll a2, ll m2, ll &a3, ll &m3) { + ll d = __gcd(m1, m2), c = a2 - a1; + if (c % d != 0) { return false; } + c = (c % m2 + m2) % m2 / d; m1 /= d; m2 /= d; + c = c * inv(m1, m2) % m2 * m1 * d + a1; + m3 = m1 * m2 * d; a3 = (c % m3 + m3) % m3; + return true; +} +ll CRT(ll a[], ll m[], int k) { + ll a1 = a[0], m1 = m[0]; + for (int i = 1; i < k; i++) { + ll a2 = a[i], m2 = m[i], m3, a3; + if (!merge(a1, m1, a2, m2, a3, m3)) { return -1; } + a1 = a3; m1 = m3; + } + return (a1 % m1 + m1) % m1; +} +//模线性方程组 需扩展欧几里得 +//求解方程ax ≡ b (mod m) 相当于求解方程ax + my = b (x, y为整数) +int m[10], a[10]; //模数为m, 余数为a, X % m = a +bool solve(int &m0, int &a0, int m, int a) { + ll y, x, d = exgcd(m0, m, x, y); + if (abs(a - a0) % d) { return false; } + x *= (a - a0) / d; x %= m / d; + a0 = (x * m0 + a0); m0 *= m / d; a0 %= m0; + if (a0 < 0) { a0 += m0; } + return true; +} +//无解返回false, 有解返回true +//解的形式最后为a0 + m0 * t (0 <= a0 < m0) +bool MLES(int &m0, int &a0, int n) { //解为X = a0 + m0 * k + bool flag = true; m0 = 1; a0 = 0; + for (int i = 0; i < n; i++) { + if (!solve(m0, a0, m[i], a[i])) { flag = false; break; } + } + return flag; +} +//求原根 +ll fac[N]; +ll getRoot(ll n) { + int cnt = 0; + for (ll i = 2; i * i < n - 1; i++) { if ((n - 1) % i == 0) { fac[cnt++] = i; fac[cnt++] = (n - 1) / i; } } + for (int i = 2, j;; i++) { + for (j = 0; j < cnt; j++) { if (powMod(i, fac[j], n) == 1) { break; } } + if (j == cnt) { return i; } + } +} +//线性基 +//异或线性基 +//若要查询第k小子集异或和, 则把k写成二进制, 对于是1的第i位, 把从低位到高位第i个不为0的数异或进答案 +//若要判断是否有非空子集的异或和为0, 如果不存在自由基, 那么说明只有空集的异或值为0, 需要高斯消元来判断 +struct XORBase { + int a[64]; + void clear() { memset(a, 0, sizeof(a)); } + void ins(ll x) { + for (int i = 62; i >= 0; i--) { + if (x & (1 << i)) { + if (a[i]) { x ^= a[i]; } + else { a[i] = x; } + break; + } + } + } + //查询最大子集异或和 + void query() { + ll ret = 0; + for (int i = 62; i >= 0; i--) { ret = max(ret, ret ^ a[i]); } + return ret; + } +}; +//实数线性基 +//ins返回要插入的数是否可以被之前的数线性表示出来, 返回true表示不能, false表示可以 +int m; +struct Base { + double a[N][N]; bool v[N]; + void clear() { memset(a, 0, sizeof(a)); memset(v, 0, sizeof(v)); } + bool ins(double *x) { + for (int i = 0; i < m; i++) { + if (fabs(x[i]) > 1e-6) { + if (v[i]) { + double t = x[i] / a[i][i]; + for (int j = 0; j < m; j++) { x[j] -= t * a[i][j]; } + } else { + v[i] = 1; + for (int j = 0; j < m; j++) { a[i][j] = x[j]; } + return true; + } + } + } + return false; + } +}; +//离散对数 大步小步算法 Baby-Step Giant-Step +//BSGS(a, b, p): 求ax = b (mod p)的最小非负整数解, 若无解则返回 -1 +//rev(a, p): 扩展欧几里得求逆元 +//powMod(base, pow, mod): 快速幂 +//mulMod(a, b, mod): 快速乘(这里用快速乘是为了避免爆long long int, 实际有时可以不用) +unordered_map Hash; +ll BSGS(ll a, ll b, ll p) { + if (b >= p) { return -1; } + a %= p, b %= p; + if (!a && !b) { return 1; } //a和b都是p的倍数的话, 就相当于0^x = 0 (mod p)了, 那么最小非负整数解就是1 + if (!a) { return -1; } //如果a是p的倍数但是b不是, 就相当于0^x = t (mod p), t > 0, 无解 + Hash.clear(); + ll m = ceil(sqrt(p)), tmp = 1 % p; //tmp = a^j + for (ll j = 0; j < m; j++) { //预处理出a^j mod p的值 + Hash[tmp] = j; tmp = mulMod(tmp, a, p); + } + tmp = rev(powMod(a, m, p), p); //tmp = a^(-m) + for (ll i = 0; i < m; i++) { + if (Hash.find(b) != Hash.end()) { return i * m + Hash[b]; } + b = mulMod(b, tmp, p); + } + return -1; +} +//高斯消元 求线性方程组的解 O(n^3) +//有equ个方程, var个变元, 增广矩阵行数为equ, 列数为var + 1, 下标从0开始 +int a[N][N], x[N]; //增广矩阵, 解集 +int freex[N], freenum;//自由变元 (多解枚举自由变元可以使用) +//返回值为-1表示无解, 为0是唯一解, 否则返回自由变元个数 +int Gauss(int equ, int var) { + int mxrow, col, k; freenum = 0; + for (k = 0, col = 0; k < equ && col < var; k++, col++) { + mxrow = k; + for (int i = k + 1; i < equ; i++) { if (abs(a[i][col]) > abs(a[mxrow][col])) { mxrow = i; } } + if (a[mxrow][col] == 0) { k--; freex[freenum++] = col; continue; } //自由变元 + if (mxrow != k) { for (int j = col; j <= var; j++) { swap(a[k][j], a[mxrow][j]); } } + for (int i = k + 1; i < equ; i++) { + if (a[i][col]) { + int x = abs(a[i][col]), y = abs(a[k][col]), lcm = x / __gcd(x, y) * y, tx = lcm / x, ty = lcm / y; + if (a[i][col] * a[k][col] < 0) { ty = -ty; } + for (int j = col; j <= var; j++) { + a[i][j] = a[i][j] * tx - a[k][j] * ty; //a[i][j] = (a[i][j] % M + M) % M; + } + } + } + } + for (int i = k; i < equ; i++) { if (a[i][col]) { return -1; } } //无解 + if (k < var) { return var - k; } //自由变元个数 + for (int i = var - 1; i >= 0; i--) { //唯一解,回代 + for (int j = i + 1; j < var; j++) { + if (a[i][j]) { a[i][var] -= a[i][j] * x[j]; /*a[i][var] = (a[i][var] % M + M) % M;*/ } + } + //while (a[i][var] % a[i][i]) { a[i][var] += M; } + x[i] = a[i][var] / a[i][i]; //x[i] = (a[i][var] * inv(a[i][i], M)) % M; + } + return 0; +} +//高斯消元 (浮点数) +const double eps = 1e-9; +const int N = 205; +double a[N][N], x[N]; //方程的左边的矩阵和等式右边的值, 求解之后x存的就是结果 +int equ, var; //方程数和未知数个数 +//返回0表示无解, 1表示有解 +int Gauss() { + int i, j, k, col, mxrow; + for (k = 0, col = 0; k < equ && col < var; k++, col++) { + mxrow = k; + for (i = k + 1; i < equ; i++) { + if (fabs(a[i][col]) > fabs(a[mxrow][col])) { mxrow = i; } + } + if (fabs(a[mxrow][col]) < eps) { return 0; } + if (k != mxrow) { + for (j = col; j < var; j++) { swap(a[k][j], a[mxrow][j]); } + swap(x[k], x[mxrow]); + } + x[k] /= a[k][col]; + for (j = col + 1; j < var; j++) { a[k][j] /= a[k][col]; } + a[k][col] = 1; + for (i = 0; i < equ; i++) { + if (i != k) { + x[i] -= x[k] * a[i][k]; + for (j = col + 1; j < var; j++) { a[i][j] -= a[k][j] * a[i][col]; } + a[i][col] = 0; + } + } + } + return 1; +} +//自适应simpson积分 +//给定一个函数f(x), 求[a, b]区间内f(x)到x轴所形成区域的面积 +double simpson(double l, double r) {return (f(l) + f(r) + 4 * f((l + r) / 2.0)) * (r - l) / 6.0;} +double rsimpson(double l, double r) { + double mid = (l + r) / 2.0; + if (fabs(simpson(l, r) - simpson(l, mid) - simpson(mid, r)) < EPS) { + return simpson(l, mid) + simpson(mid, r); + } + return rsimpson(l, mid) + rsimpson(mid, r); +} +//FFT O(nlogn) +//以下n必须为2的幂, op为1时是求DFT, op为-1时为求IDFT +typedef complex comp; +const double PI = acos(-1.0); +void fft(comp a[], int n, int op) { + for (int i = 1, j = 0; i < n - 1; i++) { + for (int s = n; j ^= s >>= 1, ~j & s;); + if (i < j) { swap(a[i], a[j]); } + } + for (int i = 1; i < n; i <<= 1) { + comp wn(cos(PI / i), op * sin(PI / i)); + for (int j = 0; j < n; j += i << 1) { + comp w(1, 0); + for (int k = 0; k < i; k++, w *= wn) { + comp x = a[j + k], y = w * a[i + j + k]; + a[j + k] = x + y; a[i + j + k] = x - y; + } + } + } + if (op == -1) { for (int i = 0; i < n; i++) { a[i] = comp(a[i].real() / n, a[i].imag()); } } +} +//求高精度乘法 HDU 1402 +comp a[N], b[N]; +char str1[N / 2], str2[N / 2]; +int sum[N]; +int main() { + while (~scanf("%s%s", str1, str2)) { + memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); + int n = strlen(str1), m = strlen(str2), len = 1; + while (len < n * 2 || len < m * 2) { len <<= 1; } + for (int i = 0; i < n; i++) { a[i] = comp(str1[n - 1 - i] - '0', 0); } + for (int i = 0; i < m; i++) { b[i] = comp(str2[m - 1 - i] - '0', 0); } + fft(a, len, 1); fft(b, len, 1); + for (int i = 0; i < len; i++) { a[i] *= b[i]; } + fft(a, len, -1); + for (int i = 0; i < len; i++) { sum[i] = (int)(a[i].real() + 0.5); } + for (int i = 0; i < len; i++) { sum[i + 1] += sum[i] / 10; sum[i] %= 10; } + len = n + m - 1; + while (sum[len] <= 0 && len > 0) { len--; } + for (int i = len; i >= 0; i--) { putchar(sum[i] + '0'); } puts(""); + } +} +//NTT O(nlogn) +//998244353 = 119 * 2^23 + 1, 原根为3; 1004535809 = 479 * 2^21 + 1, 原根为3 +//786433 = 3 * 2^18 + 1, 原根为10; 880803841 = 105 * 2^23 + 1, 原根为26 +//P是素数且N必须是P - 1的因子 +//op为1时是求FNT, op为-1时为求IFNT +const int P = 998244353, G = 3, N = 262144, K = 17; +ll g[N + 5], ng[N + 5], Inv[N + 5] = {1, 1}; +void initG() { + g[K] = powMod(G, (P - 1) / N, P); ng[K] = powMod(g[K], P - 2, P); + for (int i = K - 1; i >= 0; i--) { g[i] = g[i + 1] * g[i + 1] % P; ng[i] = ng[i + 1] * ng[i + 1] % P; } + for (ll i = 2; i <= N; i++) { Inv[i] = (P - P / i) * Inv[P % i] % P; } +} +void ntt(ll a[], int n, int op) { + for (int i = 1, j = 0; i < n - 1; i++) { + for (int s = n; j ^= s >>= 1, ~j & s;); + if (i < j) { swap(a[i], a[j]); } + } + for (int d = 0; (1 << d) < n; d++) { + int m = 1 << d; ll w0 = op == 1 ? g[d] : ng[d]; + for (int i = 0; i < n; i += m << 1) { + for (int j = 0, w = 1; j < m; j++, w = w * w0 % P) { + ll &x = a[i + j + m], &y = a[i + j], t = w * x % P; + x = y - t; y = y + t; + if (x < 0) { x += P; } if (y >= P) { y -= P; } + } + } + } + if (op == -1) { for (int i = 0; i < n; i++) { a[i] = a[i] * Inv[n] % P; } } +} +//多项式求逆元 O(nlogn) 即求B(x)满足A(X) * B(x) = 1 (mod x^n), deg(B) <= deg(A) +void polyInv(ll a[], ll b[], int n) { + if (n == 1) { b[0] = powMod(a[0], P - 2, P); return; } + polyInv(a, b, n >> 1); + int k = 1; + while (k < n << 1) { k <<= 1; } + for (int i = 0; i < n; i++) { tmp[i] = a[i]; } + for (int i = n; i < k; i++) { tmp[i] = b[i] = 0; } + ntt(tmp, k, 1); ntt(b, k, 1); + for (int i = 0; i < k; i++) { + b[i] = b[i] * (2 - tmp[i] * b[i] % P) % P; + if (b[i] < 0) { b[i] += P; } + } + ntt(b, k, -1); + for (int i = n; i < k; i++) { b[i] = 0; } +} +//多项式除法 O(nlogn) 即求D(x)和R(x)满足A(x) = D(x) * B(x) + R(x), deg(D) <= deg(A) - deg(B), deg(R) < deg(B) +ll a0[N], b0[N]; +void polyDiv(ll a[], int n, ll b[], int m, ll d[], ll r[]) { + int k = 1, t = n - m + 1; + while (k < t << 1) { k <<= 1; } + for (int i = 0; i < k; i++) { a0[i] = b0[i] = 0; } + for (int i = 0; i < m; i++) { a0[i] = b[m - i - 1]; } + polyInv(a0, b0, t); + for (int i = t; i < k; i++) { b0[i] = 0; } + for (int i = 0; i < t; i++) { a0[i] = a[n - i - 1]; } + for (int i = t; i < k; i++) { a0[i] = 0; } + ntt(b0, k, 1); ntt(a0, k, 1); + for (int i = 0; i < k; i++) { a0[i] = a0[i] * b0[i] % P; } + ntt(a0, k, -1); + reverse(a0, a0 + t); + for (int i = 0; i < t; i++) { d[i] = a0[i]; } + for (k = 1; k < n << 1; k <<= 1); + for (int i = t; i < k; i++) { a0[i] = 0; } + for (int i = 0; i < m; i++) { b0[i] = b[i]; } + for (int i = m; i < k; i++) { b0[i] = 0; } + ntt(a0, k, 1); ntt(b0, k, 1); + for (int i = 0; i < k; i++) { a0[i] = a0[i] * b0[i] % P; } + ntt(a0, k, -1); + for (int i = 0; i < m; i++) { r[i] = (a[i] - a0[i]) % P; } + for (int i = m; i < k; i++) { r[i] = 0; } +} +//多项式求对数函数 O(nlogn) a[0] = 1 +void polyLn(ll a[], ll b[], int n) { + polyInv(a, tmp2, n); + int k = 1; + while (k < n << 1) { k <<= 1; } + for (int i = 0; i < n - 1; i++) { b[i] = a[i + 1] * (i + 1) % P; } + for (int i = n - 1; i < k; i++) { b[i] = 0; } + ntt(b, k, 1); ntt(tmp2, k, 1); + for (int i = 0; i < k; i++) { b[i] = b[i] * tmp2[i] % P; } + ntt(b, k, -1); + for (int i = n - 1; i >= 0; i--) { b[i] = b[i - 1] * Inv[i] % P; } b[0] = 0; +} +//多项式求指数函数 O(nlogn) a[0] = 0 +void polyExp(ll a[], ll b[], int n) { + if (n == 1) { b[0] = 1; return; } + polyExp(a, b, n >> 1); polyLn(b, tmp, n); + int k = 1; + while (k < n << 1) { k <<= 1; } + for (int i = 0; i < n; i++) { tmp[i] -= a[i]; if (tmp[i] < 0) { tmp[i] += P; } } + if (++tmp[0] == P) { tmp[0] = 0; } + for (int i = n; i < k; i++) { tmp[i] = b[i] = 0; } + ntt(tmp, k, 1); ntt(b, k, 1); + for (int i = 0; i < k; i++) { b[i] = b[i] * tmp[i] % P; } + ntt(b, k, -1); + for (int i = n; i < k; i++) { b[i] = 0; } +} +//多项式求平方根 O(nlogn) a[0] = 1 +void polySqrt(ll a[], ll b[], int n) { + if (n == 1) { b[0] = 1; return; } + polySqrt(a, b, n >> 1); polyInv(b, tmp2, n); + int k = 1; + while (k < n << 1) { k <<= 1; } + for (int i = 0; i < n; i++) { tmp[i] = a[i]; } + for (int i = n; i < k; i++) { tmp[i] = b[i] = 0; } + ntt(tmp, k, 1); ntt(b, k, 1); ntt(tmp2, k, 1); + for (int i = 0; i < k; i++) { b[i] = (b[i] * b[i] + tmp[i]) % P * Inv[2] % P * tmp2[i] % P; } + ntt(b, k, -1); + for (int i = n; i < k; i++) { b[i] = 0; } +} +//快速沃尔什变换 即求C[i] = sum{j ? k = i}(A[j] * B[k]) ?为任一二元逻辑位运算 +void fwt(ll a[], int n) { + for (int d = 1; d < n; d <<= 1) { + for (int i = 0, m = d << 1; i < n; i += m) { + for (int j = 0; j < d; j++) { + ll x = a[i + j], y = a[i + j + d]; + //xor: a[i + j] = x + y; a[i + j + d] = x - y; + //and: a[i + j] = x + y; + //or: a[i + j + d] = x + y; + } + } + } +} +void ufwt(ll a[], int n) { + for (int d = 1; d < n; d <<= 1) { + for (int i = 0, m = d << 1; i < n; i += m) { + for (int j = 0; j < d; j++) { + ll x = a[i + j], y = a[i + j + d]; + //xor: a[i + j] = (x + y) >> 1; a[i + j + d] = (x - y) >> 1; + //and: a[i + j] = x - y; + //or: a[i + j + d] = y - x; + } + } + } +} diff --git a/.ACM-Templates/TXTs/数据结构.txt b/.ACM-Templates/TXTs/数据结构.txt new file mode 100644 index 0000000..c5b49e2 --- /dev/null +++ b/.ACM-Templates/TXTs/数据结构.txt @@ -0,0 +1,2209 @@ +//һά״ +//޸ + ѯ + ޸ + ѯ + ֵ +int n; +template struct BIT { + T A[N]; //T B[N]; ///άֵ + int lowbit(int x) { return x & -x; } + void init() { memset(A, 0, sizeof(A)); /*memset(B, 0, sizeof(B));*/ } + void update(int i, T v) { while (i <= n) { A[i] += v; i += lowbit(i); } } + T query(int i) { T ret = 0; while (i) { ret += A[i]; i -= lowbit(i); } return ret; } + T query(int i, int j) { return query(j) - query(i - 1); } + //޸ + T query(int x) { + if (!x) { return 0; } + T ret1 = 0, ret2 = 0; + for (int i = x; i <= n; i += lowbit(i)) { ret1 += A[i]; } + for (int i = x - 1; i > 0; i -= lowbit(i)) { ret2 += B[i]; } + return ret1 * x + ret2; + } + void update(int x, T v) { + for (int i = x; i > 0; i -= lowbit(i)) { A[i] += v; } + for (int i = x; i <= n; i += lowbit(i)) { B[i] += x * v; } + } + void update(int i, int j, T v) { update(j, v); if (i > 1) { update(i - 1, -v); } } + //άֵ O(log^2(n)) + void modify(int x, T v) { + B[x] = v; + for (int i = x; i <= n; i += lowbit(i)) { + A[i] = max(A[i], v); + for (int j = 1; j < lowbit(i); j <<= 1) { + A[i] = max(A[i], A[i - j]); + } + } + } + T query(int l, int r) { + T ret = B[r]; + while (true) { + ret = max(ret, B[r]); + if (l == r) { break; } + for (r -= 1; r - l >= lowbit(r); r -= lowbit(r)) { ret = max(ret, A[r]); } + } + return ret; + } + //K±/ֵ O(log^2(n)) + int getK(int l, int r, int k) { + while (l <= r) { + int mid = l + ((r - l) >> 1); + if (query(mid) >= k) { r = mid - 1; } + else { l = mid + 1; } + } + return l; //A[l] + } +}; +BIT bit; +//ά״ +//޸ + ѯ + ޸ + ѯ +int n, m; +template struct BIT { + T A[N][N]; //T B[N][N], C[N][N], D[N][N]; // + int lowbit(int x) { return x & -x; } + void init() { memset(A, 0, sizeof(A)); /*memset(B, 0, sizeof(B)); memset(C, 0, sizeof(C)); memset(D, 0, sizeof(D));*/ } + T get(int x, int y) { + T ret = 0; + for (int i = x; i > 0; i -= lowbit(i)) { for (int j = y; j > 0; j -= lowbit(j)) { ret += A[i][j]; } } + return ret; + } + T query(int x, int y) { return get(x, y) - get(x, y - 1) - get(x - 1, y) + get(x - 1, y - 1); } + void update(int x, int y, T v) { + for (int i = x; i <= n; i += lowbit(i)) { for (int j = y; j <= m; j += lowbit(j)) { A[i][j] += v; } } + } + //[x1][y1]-[x2][y2] + T query(int x1, int y1, int x2, int y2) { + return get(x2, y2) - get(x1 - 1, y2) - get(x2, y1 - 1) + get(x1 - 1, y1 - 1); + } + // + void update(int x, int y, T v, T a[][N]) { + for (int i = x; i <= n; i += lowbit(i)) { for (int j = y; j <= m; j += lowbit(j)) { a[i][j] += v; } } + } + void update(int x1, int y1, int x2, int y2, T v) { + update(x1, y1, v, A); update(x2 + 1, y1, -v, A); + update(x1, y2 + 1, -v, A); update(x2 + 1, y2 + 1, v, A); + update(x1, y1, v * x1, B); update(x2 + 1, y1, -v * (x2 + 1), B); + update(x1, y2 + 1, -v * x1, B); update(x2 + 1, y2 + 1, v * (x2 + 1), B); + update(x1, y1, v * y1, C); update(x2 + 1, y1, -v * y1, C); + update(x1, y2 + 1, -v * (y2 + 1), C); update(x2 + 1, y2 + 1, v * (y2 + 1), C); + update(x1, y1, v * x1 * y1, D); update(x2 + 1, y1, -v * (x2 + 1) * y1, D); + update(x1, y2 + 1, -v * x1 * (y2 + 1), D); update(x2 + 1, y2 + 1, v * (x2 + 1) * (y2 + 1), D); + } +}; +BIT bit; +//߶ ޸ + ѯ +#define lson l,m,rt<<1 +#define rson m+1,r,rt<<1|1 +template struct SegmentTree { + T data[N << 2]; + T calc(const T &x, const T &y)const { return x + y; } + void push_up(int rt) { data[rt] = calc(data[rt << 1], data[rt << 1 | 1]); } + void build(int l, int r, int rt) { + if (l == r) { scanf("%d", &data[rt]); return; } + int m = (l + r) >> 1; + build(lson); + build(rson); + push_up(rt); + } + void update(int p, T val, int l, int r, int rt) { + if (l == r) { data[rt] += val; return; } + int m = (l + r) >> 1; + if (p <= m) { update(p, val, lson); } + else { update(p, val, rson); } + push_up(rt); + } + T query(int L, int R, int l, int r, int rt) { + if (L <= l && r <= R) { return data[rt]; } + int m = (l + r) >> 1; T ret = 0; + if (L <= m) { ret = calc(ret, query(L, R, lson)); } + if (m < R) { ret = calc(ret, query(L, R, rson)); } + return ret; + } +}; +SegmentTree st; +//߶ ѯ/޸ + ӳٱ +#define lson l,m,rt<<1 +#define rson m+1,r,rt<<1|1 +template struct SegmentTree { + T data[N << 2], lazy[N << 2]; + T calc(const T &x, const T &y)const { return x + y; } + void push_up(int rt) { data[rt] = calc(data[rt << 1], data[rt << 1 | 1]); } + void push_down(int rt, int len) { + if (lazy[rt]) { + data[rt << 1] += lazy[rt] * (len - (len >> 1)); lazy[rt << 1] += lazy[rt]; + data[rt << 1 | 1] += lazy[rt] * (len >> 1); lazy[rt << 1 | 1] += lazy[rt]; + lazy[rt] = 0; + } + } + void build(int l, int r, int rt) { + lazy[rt] = 0; + if (l == r) { scanf("%d", &data[rt]); return; } + int m = (l + r) >> 1; + build(lson); + build(rson); + push_up(rt); + } + void update(int L, int R, T val, int l, int r, int rt) { + if (L <= l && r <= R) { + data[rt] += val * (r - l + 1); + lazy[rt] += val; + return; + } + push_down(rt, r - l + 1); + int m = (l + r) >> 1; + if (L <= m) { update(L, R, val, lson); } + if (m < R) { update(L, R, val, rson); } + push_up(rt); + } + T query(int L, int R, int l, int r, int rt) { + if (L <= l && r <= R) { return data[rt]; } + push_down(rt, r - l + 1); + int m = (l + r) >> 1; T ret = 0; + if (L <= m) { ret = calc(ret, query(L, R, lson)); } + if (m < R) { ret = calc(ret, query(L, R, rson)); } + return ret; + } +}; +SegmentTree st; +//ǵݹ߶ ޸ + ѯ +const int N = ((131072 << 1) + 10); //ڵ->С䳤+2С2*2+10 +#define l(x) ((x)<<1) //x +#define r(x) (((x)<<1)|1) //xҶ +template struct zkwSegmentTree { + int m; //ײڵ + T sum[N]; // + void build(int n) { + for (m = 1; m < n + 2; m <<= 1); + for (int i = 1; i <= n; i++) { scanf("%d", &sum[m + i]); } + for (int i = m - 1; i; i--) { sum[i] = sum[l(i)] + sum[r(i)]; } + } + void update(int p, T val) { + for (sum[p += m] += val, p >>= 1; p; p >>= 1) { + sum[p] = sum[l(p)] + sum[r(p)]; + } + } + T query(int l, int r) { + T ret = 0; + for (l += m - 1, r += m + 1; l ^ r ^ 1; l >>= 1, r >>= 1) { + if (~l & 1) { ret += sum[l ^ 1]; } + if (r & 1) { ret += sum[r ^ 1]; } + } + return ret; + } +}; +zkwSegmentTree st; +//ǵݹ߶ ѯ/޸ + ӳٱ +const int N = ((131072 << 1) + 10); //ڵ->С䳤+2С2*2+10 +#define l(x) ((x)<<1) //x +#define r(x) (((x)<<1)|1) //xҶ +template struct zkwSegmentTree { + int m, h; //ײڵ ߶ + T sum[N], add[N]; // ӳٱ + void pushdown(int rt) { + for (int i = h, p; i; i--) { //Զ + if (add[p = rt >> i]) { + add[p] >>= 1; //add[p]Ϊڵ, ӽڵһ + sum[l(p)] += add[p]; add[l(p)] += add[p]; + sum[r(p)] += add[p]; add[r(p)] += add[p]; + add[p] = 0; + } + } + } + void build(int n) { + for (m = 1, h = 0; m < n + 2; m <<= 1, h++); + for (int i = 1; i <= n; i++) { scanf("%d", &sum[m + i]); } + for (int i = m - 1; i; i--) { sum[i] = sum[l(i)] + sum[r(i)]; } + } + void update(int l, int r, T val) { + l += m - 1, r += m + 1; int ll = l >> 1, rr = r >> 1; + for (pushdown(l), pushdown(r); l ^ r ^ 1; l >>= 1, r >>= 1, val <<= 1) { + if (~l & 1) { sum[l ^ 1] += val; add[l ^ 1] += val; } + if (r & 1) { sum[r ^ 1] += val; add[r ^ 1] += val; } + } + for (; ll; ll >>= 1) { sum[ll] = sum[l(ll)] + sum[r(ll)]; } + for (; rr; rr >>= 1) { sum[rr] = sum[l(rr)] + sum[r(rr)]; } + } + T query(int l, int r) { + T ret = 0; l += m - 1, r += m + 1; + for (pushdown(l), pushdown(r); l ^ r ^ 1; l >>= 1, r >>= 1) { + if (~l & 1) { ret += sum[l ^ 1]; } + if (r & 1) { ret += sum[r ^ 1]; } + } + return ret; + } +}; +zkwSegmentTree st; +//ɳ־û߶ +const int N = 100005; +const int M = 2500005; +const int INF = 0x3f3f3f3f; +int n, m, nn; //ɢС +#define lson l,m,ls[rt] +#define rson m+1,r,rs[rt] +template struct SegmentTree { + int ls[M], rs[M], root[N], tot; T data[M]; + int new_node() { return ++tot; } + void build(int l, int r, int &rt) { + rt = new_node(); data[rt] = 0; + if (l == r) { return; } + int m = (l + r) >> 1; + build(lson); + build(rson); + } + void update(int p, T val, int lst, int l, int r, int &rt) { + rt = new_node(); ls[rt] = ls[lst]; rs[rt] = rs[lst]; data[rt] = data[lst] + val; + if (l == r) { return; } + int m = (l + r) >> 1; + if (p <= m) { update(p, val, ls[lst], lson); } + else { update(p, val, rs[lst], rson); } + } + //޸kС + int tree[N], use[N]; + int lowbit(int x) { return x & -x; } + void modify(int x, int p, T val) { //xΪԭе±, pΪֵ + for (int i = x; i <= n; i += lowbit(i)) { update(p, val, tree[i], 1, nn, tree[i]); } + } + T query(int x) { + T ret = 0; + for (int i = x; i; i -= lowbit(i)) { ret += data[ls[use[i]]]; } + return ret; + } + int query(int L, int R, int k, int l, int r) { + for (int i = L; i; i -= lowbit(i)) { use[i] = tree[i]; } + for (int i = R; i; i -= lowbit(i)) { use[i] = tree[i]; } + int lr = root[L], rr = root[R]; + while (l < r) { + int m = (l + r) >> 1; T tmp = query(R) - query(L) + data[ls[rr]] - data[ls[lr]]; + if (k <= tmp) { + r = m; + for (int i = L; i; i -= lowbit(i)) { use[i] = ls[use[i]]; } + for (int i = R; i; i -= lowbit(i)) { use[i] = ls[use[i]]; } + lr = ls[lr]; rr = ls[rr]; + } else { + l = m + 1; k -= tmp; + for (int i = L; i; i -= lowbit(i)) { use[i] = rs[use[i]]; } + for (int i = R; i; i -= lowbit(i)) { use[i] = rs[use[i]]; } + lr = rs[lr]; rr = rs[rr]; + } + } + return l; + } +}; +SegmentTree st; +//ZOJ 2112 +int a[N], hs[N], l[N], r[N], k[N]; +char op[N]; +int main() { + int C = 0, T; + scanf("%d", &T); + while (++C <= T) { + nn = 0; + scanf("%d%d", &n, &m); + for (int i = 1; i <= n; i++) { + scanf("%d", &a[i]); hs[++nn] = a[i]; + } + for (int i = 0; i < m; i++) { + scanf(" %c%d%d", &op[i], &l[i], &r[i]); + switch (op[i]) { + case 'Q': scanf("%d", &k[i]); break; + case 'C': hs[++nn] = r[i]; break; + } + } + sort(hs + 1, hs + nn + 1); + nn = unique(hs + 1, hs + nn + 1) - hs - 1; + for (int i = 1; i <= n; ++i) { + a[i] = lower_bound(hs + 1, hs + nn + 1, a[i]) - hs; + } + st.tot = 0; + st.build(1, nn, st.root[0]); + for (int i = 1; i <= n; i++) { + st.update(a[i], 1, st.root[i - 1], 1, nn, st.root[i]); + } + for (int i = 1; i <= n; i++) { st.tree[i] = st.root[0]; } + for (int i = 0; i < m; i++) { + switch (op[i]) { + case 'Q': + printf("%d\n", hs[st.query(l[i] - 1, r[i], k[i], 1, nn)]); + break; + case 'C': + st.modify(l[i], a[l[i]], -1); + a[l[i]] = lower_bound(hs + 1, hs + nn + 1, r[i]) - hs; + st.modify(l[i], a[l[i]], 1); + break; + } + } + } +} +//ʵʱڵȨֵ߶ (ɢ) O(logV) +const int N = 60005; +const int M = 2500005; +const int INF = 0x3f3f3f3f; +int n, a[N]; +#define lson l,m,ls[rt] +#define rson m+1,r,rs[rt] +struct SegmentTree { + int ls[M], rs[M], cnt[M], root[N], tot; + void init() { + tot = 0; memset(cnt, 0, sizeof(cnt)); memset(root, 0, sizeof(root)); + memset(ls, 0, sizeof(ls)); memset(rs, 0, sizeof(rs)); + } + int new_node() { return ++tot; } + void update(int p, int val, int l, int r, int &rt) { + if (!rt) { rt = new_node(); } + if (l == r) { cnt[rt] += val; return; } + int m = (l + r) >> 1; + if (p <= m) { update(p, val, lson); } + else { update(p, val, rson); } + cnt[rt] = cnt[ls[rt]] + cnt[rs[rt]]; + } + int use[N]; + int lowbit(int x) { return x & -x; } + //޸ + void modify(int x, int p, int val) { + for (int i = x; i <= n; i += lowbit(i)) { update(p, val, 0, INF, root[i]); } + } + int query(int x) { + int ret = 0; + for (int i = x; i; i -= lowbit(i)) { ret += cnt[ls[use[i]]]; } + return ret; + } + //ѯkС + int query(int L, int R, int k, int l, int r) { + for (int i = L; i; i -= lowbit(i)) { use[i] = root[i]; } + for (int i = R; i; i -= lowbit(i)) { use[i] = root[i]; } + while (l < r) { + int m = (l + r) >> 1, tmp = query(R) - query(L); + if (k <= tmp) { + r = m; + for (int i = L; i; i -= lowbit(i)) { use[i] = ls[use[i]]; } + for (int i = R; i; i -= lowbit(i)) { use[i] = ls[use[i]]; } + } else { + l = m + 1; k -= tmp; + for (int i = L; i; i -= lowbit(i)) { use[i] = rs[use[i]]; } + for (int i = R; i; i -= lowbit(i)) { use[i] = rs[use[i]]; } + } + } + return l; + } +} st; +//BZOJ1901 kС +int main() { + int m, l, r, k; char op[5]; + while (~scanf("%d%d", &n, &m)) { + st.init(); + for (int i = 1; i <= n; ++i) { + scanf("%d", &a[i]); + st.modify(i, a[i], 1); + } + while (m--) { + scanf("%s%d%d", op, &l, &r); + switch (op[0]) { + case 'Q': + scanf("%d", &k); + printf("%d\n", st.query(l - 1, r, k, 0, INF)); + break; + case 'C': + st.modify(l, a[l], -1); + a[l] = r; + st.modify(l, a[l], 1); + break; + } + } + } +} +//ƽ ò +//עЩڲظֵƽ(setmultiset) +//ظֵ(ӵcnt)ʵ, ֻҪһЩ+1ĵط޸(ijcnt[x]) +bool find(int v) { + for (int x = root; x; x = ch[x][key[x] < v]) { + if (key[x] == v) { return true; } + } + return false; +} +int getKth(int k) { + int x = root; + while (size[ch[x][0]] + 1 != k) { + if (k < size[ch[x][0]] + 1) { x = ch[x][0]; } + else { k -= size[ch[x][0]] + 1; x = ch[x][1]; } + } + return key[x]; +} +int getRank(int v) { + int ret = 0, x = root; + while (x) { + if (v < key[x]) { x = ch[x][0]; } + else { ret += size[ch[x][0]] + 1; x = ch[x][1]; } + } + return ret; +} +int getPre(int v) { + int x = root, y = 0; + while (x) { + if (v < key[x]) { x = ch[x][0]; } + else { y = x; x = ch[x][1]; } + } + return y; +} +int getNext(int v) { + int x = root, y = 0; + while (x) { + if (v > key[x]) { x = ch[x][1]; } + else { y = x; x = ch[x][0]; } + } + return y; +} +int getMin() { + if (size[root] == 0) { return -1; } + int x = root; + while (ch[x][0]) { x = ch[x][0]; } + return x; +} +int getMax() { + if (size[root] == 0) { return -1; } + int x = root; + while (ch[x][1]) { x = ch[x][1]; } + return x; +} +//Debug +void treaval(int x) { + if (x != 0) { + treaval(ch[x][0]); + printf("Node%2d:lson %2d rson %2d size = %2d ,val = %2d\n", x, ch[x][0], ch[x][1], size[x], key[x]); + treaval(ch[x][1]); + } +} +void debug() { + printf("root:%d\n", root); + treaval(root); + putchar('\n'); +} +//תTreap ظֵ +//άеԺͶѵ, ֵ, +//ĸ߶άƽij̶,Ӷʵ˸ֲO(logn)ĸӶ. +//Լ۱ȸֻת(ҿԺϲд), ȺAVLС +struct Treap { + int tot, root; + int ch[N][2], key[N], pt[N], cnt[N], size[N]; + void init() { tot = root = 0; pt[0] = INF; } + void push_up(int x) { size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x]; } + void new_node(int &x, int v) { + x = ++tot; + ch[x][0] = ch[x][1] = 0; + size[x] = cnt[x] = 1; + pt[x] = rand(); + key[x] = v; + } + void rotate(int &x, int f) { + int y = ch[x][f]; + ch[x][f] = ch[y][f ^ 1]; + ch[y][f ^ 1] = x; + push_up(x); + push_up(y); + x = y; + } + void insert(int &x, int v) { + if (!x) { new_node(x, v); return; } + if (key[x] == v) { + ++cnt[x]; + } else { + int f = key[x] < v; + insert(ch[x][f], v); + if (pt[ch[x][f]] < pt[x]) { + rotate(x, f); + } + } + push_up(x); + } + void erase(int &x, int v) { + if (!x) { return; } + if (key[x] == v) { + if (cnt[x] > 1) { + --cnt[x]; + } else { + if (!ch[x][0] && !ch[x][1]) { + x = 0; + } else { + rotate(x, pt[ch[x][0]] > pt[ch[x][1]]); + erase(x, v); + } + } + } else { + erase(ch[x][key[x] < v], v); + } + push_up(x); + } + void insert(int v) { insert(root, v); } + void erase(int v) { erase(root, v); } +} treap; +//Size Balanced Tree ظֵ +//صƽ̯ʱO(1)Maintain, нںʱЧ +struct SBT { + int root, tot; + int ch[N][2], key[N], size[N]; + void init() { tot = root = 0; size[0] = 0; } + void rotate(int &x, int f) { + int y = ch[x][f]; + ch[x][f] = ch[y][f ^ 1]; + ch[y][f ^ 1] = x; + size[y] = size[x]; + size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; + x = y; + } + void maintain(int &x, int f) { + if (size[ch[ch[x][f]][f]] > size[ch[x][f ^ 1]]) { + rotate(x, f); + } else if (size[ch[ch[x][f]][f ^ 1]] > size[ch[x][f ^ 1]]) { + rotate(ch[x][f], f ^ 1); rotate(x, f); + } else { + return; + } + maintain(ch[x][0], 0); + maintain(ch[x][1], 1); + maintain(x, 0); + maintain(x, 1); + } + void insert(int &x, int v) { + if (!x) { + x = ++tot; + ch[x][0] = ch[x][1] = 0; + size[x] = 1; + key[x] = v; + } else { + ++size[x]; + insert(ch[x][key[x] < v], v); + maintain(x, key[x] < v); + } + } + int erase(int &x, int v) { + if (!x) { return 0; } + --size[x]; + if (key[x] == v || (key[x] > v && !ch[x][0]) || (key[x] < v && !ch[x][1])) { + int ret = key[x]; + if (ch[x][0] && ch[x][1]) { + key[x] = erase(ch[x][0], v + 1); + } else { + x = ch[x][0] + ch[x][1]; + } + return ret; + } + return erase(ch[x][key[x] < v], v); + } + void insert(int v) { insert(root, v); } + void erase(int v) { erase(root, v); } +} sbt; +//Splay +//ʵֺܶƽ޷ʵֵIJ(䷭ת), ȿάϢ, +//ҲάϢ, Treap, Ҳ߶. +//Ҫ, Splayʵsplit(ijԭз)merge(ijһ), +//ҲʹɾΪ. вdzԴ, ԼTreap1.53, ߶25. +//Splayе˫ʵ, ֻ˫֤˾̯O(logn)ĵβӶ, +//ΪܶΪzigzag̫(OIѡд), ѡ˵. +//ʵȫ΢ʧһ㳣, ϲһrotate˫. +//һõʵͨҪһһβڱڵ, Լٺ߽ܶ. +//бҪеչ˵, һ, ҪάϢ, ǿSplayά(dfs), +//split䣻SplayάdfsĽṹ, Euler-Tour Tree. +//ͬ, ҪάϢ, ʷȻSplayάÿ, +//07Ҽѵҵļ, ܷõĸӶȻǵβ̯O(logn)Ӷ; +//Ƶ˼Щת, ͱ˺ᵽLink-Cut Tree(¼LCT). +//ver.1 +#define keyTree (ch[ch[root][1]][0]) +const int N = 200005; +const int INF = 0x3f3f3f3f; +int num[N]; +struct Splay { + int root, tot1, tot2; + int ch[N][2], pre[N], size[N]; + int gc[N], que[N]; + int key[N], vmin[N], add[N], rev[N]; + void rotate(int x, int f) { + int y = pre[x]; + ch[y][f ^ 1] = ch[x][f]; + pre[ch[x][f]] = y; + pre[x] = pre[y]; + if (pre[x]) { + ch[pre[y]][ch[pre[y]][1] == y] = x; + } + ch[x][f] = y; + pre[y] = x; + push_up(y); + } + void splay(int x, int goal) { + push_down(x); + while (pre[x] != goal) { + int y = pre[x], z = pre[y]; + if (z == goal) { + push_down(y); + push_down(x); + rotate(x, ch[y][0] == x); + } else { + push_down(z); + push_down(y); + push_down(x); + int f = ch[z][0] == y; + if (ch[y][f] == x) { + rotate(x, f ^ 1); + } else { + rotate(y, f); + } + rotate(x, f); + } + } + push_up(x); + if (goal == 0) { + root = x; + } + } + void rotate_to(int k, int goal) { + int x = root; + push_down(x); + while (size[ch[x][0]] != k) { + if (k < size[ch[x][0]]) { + x = ch[x][0]; + } else { + k -= size[ch[x][0]] + 1; + x = ch[x][1]; + } + push_down(x); + } + splay(x, goal); + } + void erase(int x) { + int fa = pre[x], head = 0, tail = 0; + for (que[tail++] = x; head < tail; ++head) { + gc[tot2++] = que[head]; + if (ch[que[head]][0]) { + que[tail++] = ch[que[head]][0]; + } + if (ch[que[head]][1]) { + que[tail++] = ch[que[head]][1]; + } + } + ch[fa][ch[fa][1] == x] = 0; + push_up(fa); + } + void new_node(int &x, int v, int fa) { + if (tot2) { + x = gc[--tot2]; + } else { + x = ++tot1; + } + ch[x][0] = ch[x][1] = 0; + pre[x] = fa; + size[x] = 1; + key[x] = vmin[x] = v; + add[x] = rev[x] = 0; + } + void update_add(int x, int d) { + if (x) { + key[x] += d; + add[x] += d; + vmin[x] += d; + } + } + void update_rev(int x) { + if (x) { + swap(ch[x][0], ch[x][1]); + rev[x] ^= 1; + } + } + void push_up(int x) { + size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; + vmin[x] = min(key[x], min(vmin[ch[x][0]], vmin[ch[x][1]])); + } + void push_down(int x) { + if (add[x]) { + update_add(ch[x][0], add[x]); + update_add(ch[x][1], add[x]); + add[x] = 0; + } + if (rev[x]) { + update_rev(ch[x][0]); + update_rev(ch[x][1]); + rev[x] = 0; + } + } + void build(int &x, int l, int r, int f) { + int m = l + r >> 1; + new_node(x, num[m], f); + if (l < m) { + build(ch[x][0], l, m - 1, x); + } + if (r > m) { + build(ch[x][1], m + 1, r, x); + } + push_up(x); + } + void init(int n) { + root = tot1 = tot2 = 0; + ch[0][0] = ch[0][1] = pre[0] = size[0] = 0; + add[0] = rev[0] = 0; + key[0] = vmin[0] = INF; + new_node(root, -1, 0); + new_node(ch[root][1], -1, root); + size[root] = 2; + for (int i = 1; i <= n; ++i) { + scanf("%d", &num[i]); + } + build(keyTree, 1, n, ch[root][1]); + push_up(ch[root][1]); + push_up(root); + } + void plus(int l, int r, int v) { + rotate_to(l - 1, 0); + rotate_to(r + 1, root); + update_add(keyTree, v); + } + void reverse(int l, int r) { + rotate_to(l - 1, 0); + rotate_to(r + 1, root); + update_rev(keyTree); + } + void revolve(int l, int r, int k) { + k %= r - l + 1; + if (!k) { + return; + } + rotate_to(r - k, 0); + rotate_to(r + 1, root); + int tmp = keyTree; + keyTree = 0; + push_up(ch[root][1]); + push_up(root); + rotate_to(l - 1, 0); + rotate_to(l, root); + keyTree = tmp; + pre[tmp] = ch[root][1]; + push_up(ch[root][1]); + push_up(root); + } + void insert(int k, int v) { + rotate_to(k, 0); + rotate_to(k + 1, root); + new_node(keyTree, v, ch[root][1]); + push_up(ch[root][1]); + push_up(root); + } + void del(int k) { + rotate_to(k - 1, 0); + rotate_to(k + 1, root); + erase(keyTree); + push_up(ch[root][1]); + push_up(root); + } + int query(int l, int r) { + rotate_to(l - 1, 0); + rotate_to(r + 1, root); + return vmin[keyTree]; + } +} splay; +int main() { + int n, m, x, y, v; + char op[10]; + while (~scanf("%d", &n)) { + splay.init(n); + scanf("%d", &m); + while (m--) { + scanf("%s", op); + switch (op[0]) { + case 'A': + scanf("%d%d%d", &x, &y, &v); + splay.plus(x, y, v); + break; + case 'R': + scanf("%d%d", &x, &y); + if (op[3] == 'E') { + splay.reverse(x, y); + } else { + scanf("%d", &v); + splay.revolve(x, y, v); + } + break; + case 'I': + scanf("%d%d", &x, &v); + splay.insert(x, v); + break; + case 'D': + scanf("%d", &x); + splay.del(x); + break; + case 'M': + scanf("%d%d", &x, &y); + printf("%d\n", splay.query(x, y)); + break; + } + } + } +} +//ver.2 +int k1, k2, num[N]; +struct Splay { + int root, tot, point; + int ch[N][2], pre[N], size[N]; + int key[N], add[N], rev[N]; + bool isroot(int x) { return !pre[x] || ch[pre[x]][0] != x && ch[pre[x]][1] != x; } + void rotate(int x) { + int y = pre[x], f = ch[y][1] == x; + ch[y][f] = ch[x][f ^ 1]; + pre[ch[y][f]] = y; + if (!isroot(y)) { ch[pre[y]][ch[pre[y]][1] == y] = x; } + pre[x] = pre[y]; + ch[x][f ^ 1] = y; + pre[y] = x; + push_up(y); + } + void splay(int x) { + push_down(x); + while (!isroot(x)) { + int y = pre[x], z = pre[y]; + if (isroot(y)) { + push_down(y); + push_down(x); + rotate(x); + } else { + push_down(z); + push_down(y); + push_down(x); + rotate((ch[z][1] == y) == (ch[y][1] == x) ? y : x); + rotate(x); + } + } + push_up(x); + } + void new_node(int &x, int v, int fa) { + x = ++tot; + ch[x][0] = ch[x][1] = 0; + pre[x] = fa; + size[x] = 1; + key[x] = v; + add[x] = rev[x] = 0; + } + void update_add(int x, int v) { + if (x) { key[x] += v; add[x] += v; } + } + void update_rev(int x) { + if (x) { rev[x] ^= 1; swap(ch[x][0], ch[x][1]); } + } + void push_down(int x) { + if (add[x]) { + update_add(ch[x][0], add[x]); + update_add(ch[x][1], add[x]); + add[x] = 0; + } + if (rev[x]) { + update_rev(ch[x][0]); + update_rev(ch[x][1]); + rev[x] = 0; + } + } + void push_up(int x) { size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; } + void build(int &x, int l, int r, int fa) { + int m = l + r >> 1; + new_node(x, num[m], fa); + if (l < m) { build(ch[x][0], l, m - 1, x); } + if (r > m) { build(ch[x][1], m + 1, r, x); } + push_up(x); + } + void init(int n) { + root = tot = size[0] = 0; + for (int i = 1; i <= n; ++i) { + scanf("%d", &num[i]); + } + build(root, 1, n, 0); + point = 1; + } + int find(int rt, int k) { + int x = rt; + while (size[ch[x][0]] + 1 != k) { + push_down(x); + if (k <= size[ch[x][0]]) { + x = ch[x][0]; + } else { + k -= size[ch[x][0]] + 1; + x = ch[x][1]; + } + } + return x; + } + void split(int &x, int &y, int sz) { + if (!sz) { y = x; x = 0; return; } + y = find(x, sz + 1); + splay(y); + x = ch[y][0]; + ch[y][0] = 0; + push_up(y); + } + void split3(int &x, int &y, int &z, int l, int r) { + split(x, z, r); split(x, y, l - 1); + } + void join(int &x, int &y) { + if (!x || !y) { x |= y; return; } + x = find(x, size[x]); + splay(x); + ch[x][1] = y; + pre[y] = x; + push_up(x); + } + void join3(int &x, int y, int z) { + join(y, z); join(x, y); + } + void evert() { + if (point > 1) { + int x; + split(root, x, point - 1); + swap(root, x); + join(root, x); + point = 1; + } + } + void plus(int v) { + evert(); + int x, y; + split3(root, x, y, point, point + k2 - 1); + update_add(x, v); + join3(root, x, y); + } + void reverse() { + evert(); + int x, y; + split3(root, x, y, point, point + k1 - 1); + update_rev(x); + join3(root, x, y); + } + void insert(int v) { + evert(); + int x, y; + split(root, x, point); + new_node(y, v, 0); + join3(root, y, x); + } + void erase() { + evert(); + int x, y; + split3(root, x, y, point, point); + join(root, y); + } + void move(int tag) { + switch (tag) { + case 1: + if (--point == 0) { point = size[root]; } + break; + case 2: + if (++point == size[root] + 1) { point = 1; } + break; + } + } + void query() { + evert(); + int x, y; + split3(root, x, y, point, point); + printf("%d\n", key[x]); + join3(root, x, y); + } +} splay; +//HDU4453 +int main() { + int n, m, v, cas = 0; + char op[10]; + while (~scanf("%d%d%d%d", &n, &m, &k1, &k2) && (n || m || k1 || k2)) { + splay.init(n); + printf("Case #%d:\n", ++cas); + while (m--) { + scanf("%s", op); + switch (op[0]) { + case 'a': + scanf("%d", &v); + splay.plus(v); + break; + case 'r': + splay.reverse(); + break; + case 'i': + scanf("%d", &v); + splay.insert(v); + break; + case 'd': + splay.erase(); + break; + case 'm': + scanf("%d", &v); + splay.move(v); + break; + case 'q': + splay.query(); + break; + } + } + } +} +//ver.3 +const int N = 500005; +const int INF = 0x3f3f3f3f; +int n, q; +struct Splay { + int pre[N], ch[N][2], key[N], size[N]; + int root, tot1; + int sum[N], rev[N], same[N]; + int lx[N], rx[N], mx[N]; + int s[N], tot2; //ڴغ + int a[N]; + void NewNode(int &r, int father, int k) { + if (tot2) { r = s[tot2--]; } //ȡʱtot2--,ʱ++tot2 + else { r = ++tot1; } + pre[r] = father; + ch[r][0] = ch[r][1] = 0; + key[r] = k; + sum[r] = k; + rev[r] = same[r] = 0; + lx[r] = rx[r] = mx[r] = k; + size[r] = 1; + } + void Update_Rev(int r) { + if (!r) { return; } + swap(ch[r][0], ch[r][1]); + swap(lx[r], rx[r]); + rev[r] ^= 1; + } + void Update_Same(int r, int v) { + if (!r) { return; } + key[r] = v; + sum[r] = v * size[r]; + lx[r] = rx[r] = mx[r] = max(v, v * size[r]); + same[r] = 1; + } + void push_up(int r) { + int lson = ch[r][0], rson = ch[r][1]; + size[r] = size[lson] + size[rson] + 1; + sum[r] = sum[lson] + sum[rson] + key[r]; + lx[r] = max(lx[lson], sum[lson] + key[r] + max(0, lx[rson])); + rx[r] = max(rx[rson], sum[rson] + key[r] + max(0, rx[lson])); + mx[r] = max(0, rx[lson]) + key[r] + max(0, lx[rson]); + mx[r] = max(mx[r], max(mx[lson], mx[rson])); + } + void push_down(int r) { + if (same[r]) { + Update_Same(ch[r][0], key[r]); + Update_Same(ch[r][1], key[r]); + same[r] = 0; + } + if (rev[r]) { + Update_Rev(ch[r][0]); + Update_Rev(ch[r][1]); + rev[r] = 0; + } + } + void Build(int &x, int l, int r, int father) { + if (l > r) { return; } + int mid = (l + r) / 2; + NewNode(x, father, a[mid]); + Build(ch[x][0], l, mid - 1, x); + Build(ch[x][1], mid + 1, r, x); + push_up(x); + } + void Init() { + root = tot1 = tot2 = 0; + ch[root][0] = ch[root][1] = size[root] = pre[root] = 0; + same[root] = rev[root] = sum[root] = key[root] = 0; + lx[root] = rx[root] = mx[root] = -INF; + NewNode(root, 0, -1); + NewNode(ch[root][1], root, -1); + for (int i = 0; i < n; i++) { + scanf("%d", &a[i]); + } + Build(ch[ch[root][1]][0], 0, n - 1, ch[root][1]); + push_up(ch[root][1]); + push_up(root); + } + //ת,0Ϊ, 1Ϊ + void Rotate(int x, int kind) { + int y = pre[x]; + push_down(y); + push_down(x); + ch[y][!kind] = ch[x][kind]; + pre[ch[x][kind]] = y; + if (pre[y]) { ch[pre[y]][ch[pre[y]][1] == y] = x; } + pre[x] = pre[y]; + ch[x][kind] = y; + pre[y] = x; + push_up(y); + } + //Splay, rgoal + void Splay(int r, int goal) { + push_down(r); + while (pre[r] != goal) { + if (pre[pre[r]] == goal) { + push_down(pre[r]); + push_down(r); + Rotate(r, ch[pre[r]][0] == r); + } else { + push_down(pre[pre[r]]); + push_down(pre[r]); + push_down(r); + int y = pre[r]; + int kind = ch[pre[y]][0] == y; + if (ch[y][kind] == r) { + Rotate(r, !kind); + Rotate(r, kind); + } else { + Rotate(y, kind); + Rotate(r, kind); + } + } + } + push_up(r); + if (goal == 0) { root = r; } + } + int Get_kth(int r, int k) { + push_down(r); + int t = size[ch[r][0]] + 1; + if (t == k) { return r; } + if (t > k) { return Get_kth(ch[r][0], k); } + else { return Get_kth(ch[r][1], k - t); } + } + //ڵpostot + void Insert(int pos, int tot) { + for (int i = 0; i < tot; i++) { scanf("%d", &a[i]); } + Splay(Get_kth(root, pos + 1), 0); + Splay(Get_kth(root, pos + 2), root); + Build(ch[ch[root][1]][0], 0, tot - 1, ch[root][1]); + push_up(ch[root][1]); + push_up(root); + } + //ɾ + void erase(int r) { + if (!r) { return; } + s[++tot2] = r; + erase(ch[r][0]); + erase(ch[r][1]); + } + //ӵposʼɾtot + void Delete(int pos, int tot) { + Splay(Get_kth(root, pos), 0); + Splay(Get_kth(root, pos + tot + 1), root); + erase(ch[ch[root][1]][0]); + pre[ch[ch[root][1]][0]] = 0; + ch[ch[root][1]][0] = 0; + push_up(ch[root][1]); + push_up(root); + } + //ӵposʼtot޸Ϊc + void Make_Same(int pos, int tot, int c) { + Splay(Get_kth(root, pos), 0); + Splay(Get_kth(root, pos + tot + 1), root); + Update_Same(ch[ch[root][1]][0], c); + push_up(ch[root][1]); + push_up(root); + } + //posʼtotзת + void Reverse(int pos, int tot) { + Splay(Get_kth(root, pos), 0); + Splay(Get_kth(root, pos + tot + 1), root); + Update_Rev(ch[ch[root][1]][0]); + push_up(ch[root][1]); + push_up(root); + } + //õposʼtotĺ + int Get_Sum(int pos, int tot) { + Splay(Get_kth(root, pos), 0); + Splay(Get_kth(root, pos + tot + 1), root); + return sum[ch[ch[root][1]][0]]; + } + //õposʼtotӶκ + int Get_MaxSum(int pos, int tot) { + Splay(Get_kth(root, pos), 0); + Splay(Get_kth(root, pos + tot + 1), root); + return mx[ch[ch[root][1]][0]]; + } + void InOrder(int r) { + if (!r) { return; } + push_down(r); + InOrder(ch[r][0]); + printf("%d ", key[r]); + InOrder(ch[r][1]); + } +} splay; +int main() { + while (scanf("%d%d", &n, &q) == 2) { + splay.Init(); + char op[20]; + int x, y, z; + while (q--) { + scanf("%s", op); + if (strcmp(op, "INSERT") == 0) { + scanf("%d%d", &x, &y); + splay.Insert(x, y); + } else if (strcmp(op, "DELETE") == 0) { + scanf("%d%d", &x, &y); + splay.Delete(x, y); + } else if (strcmp(op, "MAKE-SAME") == 0) { + scanf("%d%d%d", &x, &y, &z); + splay.Make_Same(x, y, z); + } else if (strcmp(op, "REVERSE") == 0) { + scanf("%d%d", &x, &y); + splay.Reverse(x, y); + } else if (strcmp(op, "GET-SUM") == 0) { + scanf("%d%d", &x, &y); + printf("%d\n", splay.Get_Sum(x, y)); + } else if (strcmp(op, "MAX-SUM") == 0) { + printf("%d\n", splay.Get_MaxSum(1, splay.size[root] - 2)); + } + } + } +} +//Link-Cut Tree ̬ +//ά(ɭ)̬, O(logn)ʱ临ӶάϢ; LCTϢdz鷳. +//ĺIJaccess, ԰ijڵ㵽·е㰴Splayά, +//Ӷevert()splayʵֶϢά. +//LCTʵֳάϢϵв, ͬʱԽ۸Ӷ, +//ʵʳϴ, ܶ಻ı̬O(logn)LCTO(log^2n)ʷ߶Խ +struct LCT { + int ch[N][2], pre[N], key[N], rev[N]; + int add[N], vmax[N]; + bool isroot(int x) { return !pre[x] || ch[pre[x]][0] != x && ch[pre[x]][1] != x; } + void rotate(int x) { + int y = pre[x], f = ch[y][1] == x; + ch[y][f] = ch[x][f ^ 1]; + pre[ch[y][f]] = y; + if (!isroot(y)) { ch[pre[y]][ch[pre[y]][1] == y] = x; } + pre[x] = pre[y]; + ch[x][f ^ 1] = y; + pre[y] = x; + push_up(y); + } + void splay(int x) { + push_down(x); + while (!isroot(x)) { + int y = pre[x], z = pre[y]; + if (isroot(y)) { + push_down(y); + push_down(x); + rotate(x); + } else { + push_down(z); + push_down(y); + push_down(x); + rotate((ch[z][1] == y) == (ch[y][1] == x) ? y : x); + rotate(x); + } + } + push_up(x); + } + int access(int x) { + int y = 0; + for (; x; x = pre[x]) { + splay(x); + ch[x][1] = y; + push_up(x); + y = x; + } + return y; + } + void evert(int x) { + rev[access(x)] ^= 1; + splay(x); + } + void push_up(int x) { vmax[x] = max(max(vmax[ch[x][0]], vmax[ch[x][1]]), key[x]); } + void push_down(int x) { + if (add[x]) { + key[x] += add[x]; + if (ch[x][0]) { + add[ch[x][0]] += add[x]; + vmax[ch[x][0]] += add[x]; + } + if (ch[x][1]) { + add[ch[x][1]] += add[x]; + vmax[ch[x][1]] += add[x]; + } + add[x] = 0; + } + if (rev[x]) { + if (ch[x][0]) { rev[ch[x][0]] ^= 1; } + if (ch[x][1]) { rev[ch[x][1]] ^= 1; } + swap(ch[x][0], ch[x][1]); + rev[x] = 0; + } + } + int find_root(int x) { + while (pre[x]) { x = pre[x]; } + return x; + } + //u,vͬһ,ͨu,v֮ߵķʽ, + void link(int u, int v) { + if (find_root(u) == find_root(v)) { puts("-1"); return; } + evert(u); + pre[u] = v; + } + //u,vͬһ,u!=v,uΪĸԺ,жv丸׽ + void cut(int u, int v) { + if (u == v || find_root(u) != find_root(v)) { puts("-1"); return; } + evert(u); + access(v); + splay(v); + pre[ch[v][0]] = 0; + ch[v][0] = 0; + push_up(v); + } + //u,vͬһ,u,v֮·еĵȨw + void update(int u, int v, int w) { + if (find_root(u) != find_root(v)) { puts("-1"); return; } + evert(u); + access(v); + splay(v); + add[v] += w; + vmax[v] += w; + push_down(v); + } + //u,vͬһ, u,v֮·ϵȨֵ + void query(int u, int v) { + if (find_root(u) != find_root(v)) { puts("-1"); return; } + evert(u); + access(v); + splay(v); + printf("%d\n", vmax[v]); + } + struct graph { + int head[N], to[N << 1], next[N << 1]; + int tot; + void init() { tot = 0; memset(head, 0xff, sizeof(head)); } + void add(int u, int v) { + to[tot] = v; + next[tot] = head[u]; + head[u] = tot++; + } + } g; + void dfs(int u, int fa) { + for (int i = g.head[u]; ~i; i = g.next[i]) { + int v = g.to[i]; + if (v != fa) { + dfs(v, u); + pre[v] = u; + } + } + } + void init(int n) { + int m, x, y; + g.init(); + for (int i = 1; i < n; ++i) { + scanf("%d%d", &x, &y); + g.add(x, y); g.add(y, x); + } + memset(ch, 0, sizeof(ch)); + memset(pre, 0, sizeof(pre)); + memset(rev, 0, sizeof(rev)); + memset(add, 0, sizeof(add)); + vmax[0] = 0; + for (int i = 1; i <= n; ++i) { + scanf("%d", &key[i]); + vmax[i] = key[i]; + } + dfs(1, 0); + } +} lct; +//HDU4010 +int main() { + int n, q, op, x, y, w; + while (~scanf("%d", &n)) { + lct.init(n); + scanf("%d", &q); + while (q--) { + scanf("%d", &op); + switch (op) { + case 1: + scanf("%d%d", &x, &y); + lct.link(x, y); + break; + case 2: + scanf("%d%d", &x, &y); + lct.cut(x, y); + break; + case 3: + scanf("%d%d%d", &w, &x, &y); + lct.update(x, y, w); + break; + case 4: + scanf("%d%d", &x, &y); + lct.query(x, y); + break; + } + } + putchar('\n'); + } +} +//תTreap +int num[N]; +struct Treap { + int tot, root; + int ch[N][2], pt[N], size[N]; + int key[N], vmin[N], add[N], rev[N]; + void init() { tot = 0; } + void new_node(int &x, int v) { + x = ++tot; + ch[x][0] = ch[x][1] = 0; + size[x] = 1; + pt[x] = rand(); + key[x] = vmin[x] = v; + add[x] = rev[x] = 0; + } + void merge(int &p, int x, int y) { + if (!x || !y) { p = x | y; return; } + if (pt[x] < pt[y]) { + push_down(x); + merge(ch[x][1], ch[x][1], y); + p = x; + } else { + push_down(y); + merge(ch[y][0], x, ch[y][0]); + p = y; + } + push_up(p); + } + void split(int p, int sz, int &x, int &y) { + if (!sz) { x = 0; y = p; return; } + push_down(p); + if (size[ch[p][0]] >= sz) { + y = p; + split(ch[p][0], sz, x, ch[y][0]); + } else { + x = p; + split(ch[p][1], sz - size[ch[p][0]] - 1, ch[x][1], y); + } + push_up(p); + } + void update_add(int x, int v) { + if (x) { key[x] += v; add[x] += v; vmin[x] += v; } + } + void update_rev(int x) { + if (x) { swap(ch[x][0], ch[x][1]); rev[x] ^= 1; } + } + void push_down(int x) { + if (add[x]) { + update_add(ch[x][0], add[x]); + update_add(ch[x][1], add[x]); + add[x] = 0; + } + if (rev[x]) { + update_rev(ch[x][0]); + update_rev(ch[x][1]); + rev[x] = 0; + } + } + void push_up(int x) { + size[x] = 1; + vmin[x] = key[x]; + if (ch[x][0]) { + size[x] += size[ch[x][0]]; + vmin[x] = min(vmin[x], vmin[ch[x][0]]); + } + if (ch[x][1]) { + size[x] += size[ch[x][1]]; + vmin[x] = min(vmin[x], vmin[ch[x][1]]); + } + } + int build(int &x, int l, int r) { + int m = l + r >> 1; + new_node(x, num[m]); + if (l < m) { build(ch[x][0], l, m - 1); } + if (r > m) { build(ch[x][1], m + 1, r); } + push_up(x); + } + void plus(int l, int r, int v) { + int x, y; + split(root, l - 1, root, x); + split(x, r - l + 1, x, y); + update_add(x, v); + merge(x, x, y); + merge(root, root, x); + } + void reverse(int l, int r) { + int x, y; + split(root, l - 1, root, x); + split(x, r - l + 1, x, y); + update_rev(x); + merge(x, x, y); + merge(root, root, x); + } + void revolve(int l, int r, int k) { + int x, y, p, q; + k %= r - l + 1; + if (!k) { return; } + split(root, l - 1, root, x); + split(x, r - l + 1, x, y); + split(x, r - l + 1 - k, p, q); + merge(x, q, p); + merge(x, x, y); + merge(root, root, x); + } + void insert(int k, int v) { + int x, y; + new_node(x, v); + split(root, k, root, y); + merge(root, root, x); + merge(root, root, y); + } + void erase(int k) { + int x, y; + split(root, k - 1, root, x); + split(x, 1, x, y); + merge(root, root, y); + } + int query(int l, int r) { + int x, y, ret; + split(root, l - 1, root, x); + split(x, r - l + 1, x, y); + ret = vmin[x]; + merge(x, x, y); + merge(root, root, x); + return ret; + } +} treap; +//POJ3580 +int main() { + int n, m, x, y, v; + char op[10]; + while (~scanf("%d", &n)) { + treap.init(); + for (int i = 1; i <= n; ++i) { + scanf("%d", &num[i]); + } + treap.build(treap.root, 1, n); + scanf("%d", &m); + while (m--) { + scanf("%s", op); + switch (op[0]) { + case 'A': + scanf("%d%d%d", &x, &y, &v); + treap.plus(x, y, v); + break; + case 'R': + scanf("%d%d", &x, &y); + if (op[3] == 'E') { + treap.reverse(x, y); + } else { + scanf("%d", &v); + treap.revolve(x, y, v); + } + break; + case 'I': + scanf("%d%d", &x, &v); + treap.insert(x, v); + break; + case 'D': + scanf("%d", &x); + treap.erase(x); + break; + case 'M': + scanf("%d%d", &x, &y); + printf("%d\n", treap.query(x, y)); + break; + } + } + } +} +//ɳ־ûTreap +const int N = 50005; +const int M = 5000005; +int root[N], vs, d; +struct Treap { + int tot; + int ch[M][2], size[M]; + char key[M]; + bool hey(int x, int y) { return (ll)rand() * (size[x] + size[y]) < (ll)size[x] * RAND_MAX; } + void init() { tot = 0; } + void new_node(int &x, char v) { + x = ++tot; + ch[x][0] = ch[x][1] = 0; + size[x] = 1; + key[x] = v; + } + void copy_node(int &x, int y) { + if (!y) { x = 0; return; } + x = ++tot; + ch[x][0] = ch[y][0]; + ch[x][1] = ch[y][1]; + size[x] = size[y]; + key[x] = key[y]; + } + void merge(int &p, int x, int y) { + if (!x || !y) { + p = 0; + if (x) { copy_node(p, x); } + if (y) { copy_node(p, y); } + return; + } + if (hey(x, y)) { + copy_node(p, x); + merge(ch[p][1], ch[x][1], y); + } else { + copy_node(p, y); + merge(ch[p][0], x, ch[y][0]); + } + push_up(p); + } + void split(int p, int sz, int &x, int &y) { + if (!sz) { x = 0; copy_node(y, p); return; } + if (size[ch[p][0]] >= sz) { + copy_node(y, p); + split(ch[p][0], sz, x, ch[y][0]); + push_up(y); + } else { + copy_node(x, p); + split(ch[p][1], sz - size[ch[p][0]] - 1, ch[x][1], y); + push_up(x); + } + } + void push_up(int x) { + size[x] = 1; + if (ch[x][0]) { size[x] += size[ch[x][0]]; } + if (ch[x][1]) { size[x] += size[ch[x][1]]; } + } + void build(char str[], int &x, int l, int r) { + int m = l + r >> 1; + new_node(x, str[m]); + if (l < m) { build(str, ch[x][0], l, m - 1); } + if (r > m) { build(str, ch[x][1], m + 1, r); } + push_up(x); + } + void insert(int k, char str[]) { + int x, y, z; + build(str, x, 0, strlen(str) - 1); + split(root[vs], k, y, z); + merge(y, y, x); + merge(root[++vs], y, z); + } + void erase(int k, int sz) { + int x, y, z; + split(root[vs], k - 1, x, y); + split(y, sz, y, z); + merge(root[++vs], x, z); + } + void output(int x) { + if (ch[x][0]) { output(ch[x][0]); } + putchar(key[x]); + d += key[x] == 'c'; + if (ch[x][1]) { output(ch[x][1]); } + } + void output(int v, int k, int sz) { + int x, y, z; + split(root[v], k - 1, x, y); + split(y, sz, y, z); + output(y); + putchar('\n'); + } +} treap; +//UVa12538 +int main() { + int n, op, p, c, v; + char s[105]; + treap.init(); + vs = d = 0; + scanf("%d", &n); + while (n--) { + scanf("%d", &op); + switch (op) { + case 1: + scanf("%d%s", &p, s); + treap.insert(p - d, s); + break; + case 2: + scanf("%d%d", &p, &c); + treap.erase(p - d, c - d); + break; + case 3: + scanf("%d%d%d", &v, &p, &c); + treap.output(v - d, p - d, c - d); + break; + } + } +} +//ʷ +//ʷֽһֳlogn, ÿڵһ, +//Ӷ·޸תΪlogn޸, dz״顢߶ȸݽṹ. +//ʷֵijС, ʷֵ, ǷԽ˻(³Ϊһ), +//ʷֵЧԽǺ(O(1), Ϊֻкٵ), +//һЩ漰̬޸ĵ·άĿ, ʷ߶O(logn^2)ĵβӶˮ, +//ʵʱֲڵβO(logn)ܴLCT. +//ʷֵijʼʵdfs, dfs, +//һǵݹʹʱ, ЩĿбջ; ҳbfsʵֵĺܺõĽ. +//Ҫ˵, ڵȨ޸ֱά, ڱȨ޸, ѡһ, +//Ȩ´ȸĽڵ; ֮, ÿ㴢Ȩֵĸڵ֮ıȨ, ڵûȨֵ. +int top[N]; //top[p]ʾΪp·Ķ˽ڵ +int len[N]; //len[p]ʾ·pij +int belong[N]; //belong[v]ʾڵv· +int idx[N]; //idx[v]ʾڵv·еı, dzα +int dep[N]; //dep[v]ʾڵv +int fa[N]; //fa[v]ʾڵvĸ׽ڵ +int size[N]; //size[v]ʾԽڵvΪĽڵ +int que[N]; +bool vis[N]; +int n, cnt; //nǵ, Ŵ1n +void split() { + memset(dep, 0xff, sizeof(dep)); + int l = 0, r = 0; + que[++r] = 1; dep[1] = 0; fa[1] = -1; + while (l < r) { + int u = que[++l]; + vis[u] = false; + for (int i = g.head[u]; ~i; i = g.next[i]) { + int v = g.to[i]; + if (!~dep[v]) { que[++r] = v; dep[v] = dep[u] + 1; fa[v] = u; } + } + } + cnt = 0; + for (int i = n; i > 0; --i) { + int u = que[i], p = -1; + size[u] = 1; + for (int j = g.head[u]; ~j; j = g.next[j]) { + int v = g.to[j]; + if (vis[v]) { + size[u] += size[v]; + if (!~p || size[v] > size[p]) { p = v; } + } + } + if (!~p) { + idx[u] = len[++cnt] = 1; + belong[u] = cnt; + top[cnt] = u; + } else { + belong[u] = belong[p]; + idx[u] = ++len[belong[u]]; + top[belong[u]] = u; + } + vis[u] = true; + } +} +int fi[N], cid[N], rank[N]; +void getcid() { + fi[1] = 1; + for (int i = 2; i <= cnt; ++i) { fi[i] = fi[i - 1] + len[i - 1]; } + for (int i = 1; i <= n; ++i) { + cid[i] = fi[belong[i]] + len[belong[i]] - idx[i]; + rank[cid[i]] = i; + } +} +// ·޸ĺͲѯ޸ +int query(int x, int y) { + int ret = 0; + while (belong[x] != belong[y]) { + if (dep[top[belong[x]]] < dep[top[belong[y]]]) { swap(x, y); } + ret = max(ret, query(cid[top[belong[x]]], cid[x], 1, n, 1)); + x = fa[top[belong[x]]]; + } + if (dep[x] > dep[y]) { swap(x, y); } + ret = max(ret, query(cid[x], cid[y], 1, n, 1)); + /*Ȩ + if(x!=y) + ret=max(ret,query(cid[x]+1,cid[y],1,n,1)); + */ + return ret; +} +//һdfsͱLCAdfsּһ; ޸ľͿ޷νLCA. +//ڶdfsԽڵλý˱(Ӧbfsgetcid), +//ǿԷ˳dfs(dfsضdfsӽڵ), õһdfs. +//仰˵, ﴦʷֱ, ͬʱҲdfs. +//֪ÿĽڵdfsжһ, +//ǾͿͬʱά·Ϣ(ʷֲָӶO(logn))Ϣ(ʷֲָӶO(1)). +//BZOJ3083 ʷ߶ +const int N = 100005; +const int maxd = 18; +const int INF = 0x7fffffff; +struct graph { + int head[N], tot; + int to[N << 1], next[N << 1]; + void init() { + tot = 0; memset(head, 0xff, sizeof(head)); + } + void add(int u, int v) { + to[tot] = v; next[tot] = head[u]; head[u] = tot++; + } +} g; +int top[N], son[N]; +int dep[N], fa[N][maxd], size[N]; +int cid[N], rank[N], cnt; +void dfs1(int u) { + size[u] = 1; son[u] = -1; + for (int i = 1; i < maxd; ++i) { fa[u][i] = fa[fa[u][i - 1]][i - 1]; } + for (int i = g.head[u]; ~i; i = g.next[i]) { + int v = g.to[i]; + if (v != fa[u][0]) { + dep[v] = dep[u] + 1; fa[v][0] = u; + dfs1(v); + size[u] += size[v]; + if (!~son[u] || size[v] > size[son[u]]) { son[u] = v; } + } + } +} +void dfs2(int u, int tp) { + top[u] = tp; cid[u] = ++cnt; rank[cid[u]] = u; + if (~son[u]) { dfs2(son[u], tp); } + for (int i = g.head[u]; ~i; i = g.next[i]) { + int v = g.to[i]; + if (v != son[u] && v != fa[u][0]) { dfs2(v, v); } + } +} +void split() { + dfs1(1); cnt = 0; dfs2(1, 1); +} +int lca(int u, int v) { + if (dep[u] < dep[v]) { swap(u, v); } + int k = dep[u] - dep[v]; + for (int i = 0; i < maxd; ++i) { + if ((1 << i)&k) { u = fa[u][i]; } + } + if (u == v) { return u; } + for (int i = maxd - 1; i >= 0; --i) { + if (fa[u][i] != fa[v][i]) { u = fa[u][i]; v = fa[v][i]; } + } + return fa[u][0]; +} +int n, root, a[N]; +#define lson l,m,rt<<1 +#define rson m+1,r,rt<<1|1 +int vmin[N << 2], col[N << 2]; +void push_up(int rt) { + vmin[rt] = min(vmin[rt << 1], vmin[rt << 1 | 1]); +} +void push_down(int rt) { + if (col[rt]) { + col[rt << 1] = col[rt << 1 | 1] = vmin[rt << 1] = vmin[rt << 1 | 1] = col[rt]; + col[rt] = 0; + } +} +void build(int l, int r, int rt) { + col[rt] = 0; + if (l == r) { vmin[rt] = a[rank[l]]; return; } + int m = l + r >> 1; + build(lson); + build(rson); + push_up(rt); +} +void update(int L, int R, int val, int l, int r, int rt) { + if (L <= l && r <= R) { col[rt] = vmin[rt] = val; return; } + push_down(rt); + int m = l + r >> 1; + if (L <= m) { update(L, R, val, lson); } + if (m < R) { update(L, R, val, rson); } + push_up(rt); +} +int query(int L, int R, int l, int r, int rt) { + if (L <= l && r <= R) { return vmin[rt]; } + push_down(rt); + int m = l + r >> 1; + int ret = INF; + if (L <= m) { ret = min(ret, query(L, R, lson)); } + if (m < R) { ret = min(ret, query(L, R, rson)); } + return ret; +} +void modify(int x, int y, int d) { + while (top[x] != top[y]) { + if (dep[top[x]] < dep[top[y]]) { swap(x, y); } + update(cid[top[x]], cid[x], d, 1, n, 1); + x = fa[top[x]][0]; + } + if (dep[x] > dep[y]) { swap(x, y); } + update(cid[x], cid[y], d, 1, n, 1); +} +int query(int rt) { + if (rt == root) { return query(1, n, 1, n, 1); } + int pre = lca(root, rt); + if (pre != rt) { return query(cid[rt], cid[rt] + size[rt] - 1, 1, n, 1); } + int depth = dep[root] - dep[rt] - 1, tmp = root; + for (int i = maxd - 1; i >= 0; --i) { + if (depth & (1 << i)) { tmp = fa[tmp][i]; } + } + return min(query(1, cid[tmp] - 1, 1, n, 1), query(cid[tmp] + size[tmp], n, 1, n, 1)); +} +int main() { + int m, u, v, opt, id; + while (~scanf("%d%d", &n, &m)) { + g.init(); + for (int i = 1; i < n; ++i) { + scanf("%d%d", &u, &v); + g.add(u, v); g.add(v, u); + } + for (int i = 1; i <= n; ++i) { + scanf("%d", &a[i]); + } + split(); + build(1, n, 1); + scanf("%d", &root); + while (m--) { + scanf("%d", &opt); + switch (opt) { + case 1: scanf("%d", &root); break; + case 2: scanf("%d%d%d", &u, &v, &id); modify(u, v, id); break; + case 3: scanf("%d", &id); printf("%d\n", query(id)); break; + } + } + } +} +//KD-Tree +//άάKԾһϢ. +//ÿһάһƽпռ仮, 㼯ȽϾȵطָڸ, +//ṹһö, ߶̬͹췽Щ. +//KD-TreeһO(logn)ĵ, ԼO(n^(1-1/D))ѯʲ, Dά, ɼάԽKD-TreeԽ +//ѯʾһǰKһҪһȶнѯʱά +//HDU4347 O(n) ֵ֧IJɾ +const int N = 50005; +const int INF = ~0U >> 1; +const int DIM = 5; +#define lson l,m-1,dep+1 +#define rson m+1,r,dep+1 +int cur, K; +struct point { + int x[DIM]; + bool operator<(const point &oth)const { return x[cur] < oth.x[cur]; } + void output() { + for (int i = 0; i < K; ++i) { + printf("%d%c", x[i], i < K - 1 ? ' ' : '\n'); + } + } +} vec[N], origin[N], pt, ans[10]; +inline int sqr(int x) { return x * x; } +int dist(const point &a, const point &b) { + int ret = 0; + for (int i = 0; i < K; ++i) { ret += sqr(a.x[i] - b.x[i]); } + return ret; +} +void build(int l, int r, int dep = 0) { + if (l >= r) { return; } + int m = l + r >> 1; + cur = dep % K; + nth_element(vec + l, vec + m, vec + r + 1); + build(lson); + build(rson); +} +priority_queue> pq; +void query(const point &x, int k, int l, int r, int dep = 0) { + if (l > r) { return; } + int m = l + r >> 1, cur = dep % K; + pair tmp(dist(x, vec[m]), vec[m]); + if (pq.size() < k) { + pq.push(tmp); + } else if (pq.top().first > tmp.first) { + pq.pop(); pq.push(tmp); + } + if (x.x[cur] < vec[m].x[cur]) { + query(x, k, lson); + if (pq.top().first > sqr(x.x[cur] - vec[m].x[cur])) { query(x, k, rson); } + } else { + query(x, k, rson); + if (pq.top().first > sqr(x.x[cur] - vec[m].x[cur])) { query(x, k, lson); } + } +} +int main() { + int n, t, m; + while (~scanf("%d%d", &n, &K)) { + for (int i = 1; i <= n; ++i) { + for (int j = 0; j < K; ++j) { + scanf("%d", &origin[i].x[j]); + } + vec[i] = origin[i]; + } + build(1, n); + scanf("%d", &t); + while (t--) { + for (int i = 0; i < K; ++i) { + scanf("%d", &pt.x[i]); + } + scanf("%d", &m); + query(pt, m, 1, n); + for (int i = 0; i < m; ++i) { + ans[i] = pq.top().second; pq.pop(); + } + printf("the closest %d points are:\n", m); + for (int i = m - 1; i >= 0; --i) { ans[i].output(); } + } + } +} +//ֵ֧IJɾ +#define lson kdt[rt].ls,dep+1 +#define rson kdt[rt].rs,dep+1 +struct kdnode { + int ls, rs, x[DIM]; bool flag; //ɾ +} kdt[N]; +inline ll sqr(int x) { return (ll)x * x; } +ll dist(const kdnode &a, const kdnode &b) { + ll ret = 0; + for (int i = 0; i < DIM; ++i) { ret += sqr(a.x[i] - b.x[i]); } + return ret; +} +int root, tot; +void init() { tot = 0; root = -1; } +int add(int pt[]) { + kdt[tot].flag = false; + kdt[tot].ls = kdt[tot].rs = -1; + for (int i = 0; i < DIM; ++i) { kdt[tot].x[i] = pt[i]; } + return tot++; +} +void insert(int pt[], int rt, int dep = 0) { + dep %= DIM; + if (pt[dep] < kdt[rt].x[dep]) { + if (!~kdt[rt].ls) { kdt[rt].ls = add(pt); } + else { insert(pt, lson); } + } else { + if (!~kdt[rt].rs) { kdt[rt].rs = add(pt); } + else { insert(pt, rson); } + } +} +// +ll query(const kdnode &pt, int rt, int dep = 0) { + if (!~rt) { return INF; } + dep %= DIM; + ll ret = INF, tmp = sqr(kdt[rt].x[dep] - pt.x[dep]); + if (!kdt[rt].flag) { ret = dist(kdt[rt], pt); } + if (pt.x[dep] <= kdt[rt].x[dep]) { + ret = min(ret, query(pt, lson)); + if (tmp < ret) { ret = min(ret, query(pt, rson)); } + } + if (pt.x[dep] >= kdt[rt].x[dep]) { + ret = min(ret, query(pt, rson)); + if (tmp < ret) { ret = min(ret, query(pt, lson)); } + } + return ret; +} +//ѯжٸ +int query(int pt1[], int pt2[], int rt, int dep = 0) { + if (!~rt) { return 0; } + dep %= DIM; + int ret = 0, cur; + for (cur = 0; cur < DIM; ++cur) { + if (kdt[rt].x[cur] < pt1[cur] || kdt[rt].x[cur] > pt2[cur]) { break; } + } + if (cur == DIM) { ++ret; } + if (pt2[dep] < kdt[rt].x[dep]) { + ret += query(pt1, pt2, lson); + } else if (pt1[dep] >= kdt[rt].x[dep]) { + ret += query(pt1, pt2, rson); + } else { + ret += query(pt1, pt2, lson); + ret += query(pt1, pt2, rson); + } + return ret; +} +// +int part[20][N]; //ʾÿÿλõֵ +int sorted[N]; //Ѿõ +int tol[20][N]; //tol[p][i] ʾi1i +void build(int l, int r, int dep) { + if (l == r) { return; } + int m = l + r >> 1, cnt = m - l + 1; //ʾмֵұߵĸ + for (int i = l; i <= r; ++i) { + if (part[dep][i] < sorted[m]) { --cnt; } + } + int lpos = l, rpos = m + 1; + for (int i = l; i <= r; ++i) { + if (part[dep][i] < sorted[m]) { + part[dep + 1][lpos++] = part[dep][i]; + } else if (part[dep][i] == sorted[m] && cnt > 0) { + part[dep + 1][lpos++] = part[dep][i]; + --cnt; + } else { + part[dep + 1][rpos++] = part[dep][i]; + } + tol[dep][i] = tol[dep][l - 1] + lpos - l; + } + build(l, m, dep + 1); + build(m + 1, r, dep + 1); +} +//߲ѯk, [L, R]ҪѯС, [l, r]Ǵ +int query(int L, int R, int k, int l, int r, int dep) { + if (L == R) { return part[dep][L]; } + int m = l + r >> 1, cnt = tol[dep][R] - tol[dep][L - 1]; + if (cnt >= k) { + int tl = l + tol[dep][L - 1] - tol[dep][l - 1], tr = tl + cnt - 1; + return query(tl, tr, k, l, m, dep + 1); + } else { + int tr = R + tol[dep][r] - tol[dep][R], tl = tr - (R - L - cnt); + return query(tl, tr, k - cnt, m + 1, r, dep + 1); + } +} +//ƫ +//ɲѵһʵ, O(logn)ʱʵֶѵpushpopѵĺϲ, ԼO(1)ʱȡѶ +int val[N], ls[N], rs[N], dep[N], fa[N]; +void init(int n) { + for (int i = 1; i <= n; ++i) { + scanf("%d", &val[i]); ls[i] = rs[i] = dep[i] = 0; fa[i] = i; + } +} +int find(int x) { return x == fa[x] ? x : fa[x] = findfa(fa[x]); } +int merge(int x, int y) { + if (!x || !y) { return x | y; } + if (val[x] < val[y]) { swap(x, y); } + rs[x] = merge(rs[x], y); fa[rs[x]] = x; + if (dep[ls[x]] < dep[rs[x]]) { swap(ls[x], rs[x]); } + dep[x] = dep[rs[x]] + 1; + return x; +} +int push(int x, int y) { return merge(x, y); } +int pop(int x) { + int a = ls[x], b = rs[x]; + ls[x] = rs[x] = dep[x] = 0; + fa[x] = x; fa[a] = a; fa[b] = b; + return merge(a, b); +} +//POJ 2201 +int main() { + int n, m, x, y; + while (~scanf("%d", &n)) { + init(n); + scanf("%d", &m); + while (m--) { + scanf("%d%d", &x, &y); + int a = find(x), b = find(y); + if (a == b) { + puts("-1"); + } else { + val[a] >>= 1; val[b] >>= 1; + a = push(pop(a), a); b = push(pop(b), b); + printf("%d\n", val[merge(a, b)]); + } + } + } +} +//ѿ +//һֵԵ, , ֵֵ֮以ͬʱ, ǿΨһعһö +//keyʱ, ; ڵvalueӽڵvalue, ѵ. +//һֵеĵѿO(n)ʱڹ +//POJ2201 +const int N = 50005; +int idx[N], n; +struct Cartesian_Tree { + int root, key[N], val[N], ch[N][2], pre[N]; + void init() { + for (int i = 1; i <= n; ++i) { + scanf("%d%d", &key[i], &val[i]); + ch[i][0] = ch[i][1] = pre[i] = 0; + } + } + void build() { + static int st[N]; + int top = -1; + for (int i = 1; i <= n; ++i) { + int k = top; + while (k >= 0 && val[st[k]] > val[idx[i]]) { + --k; + } + if (~k) { + pre[idx[i]] = st[k]; + ch[st[k]][1] = idx[i]; + } + if (k < top) { + pre[st[k + 1]] = idx[i]; + ch[idx[i]][0] = st[k + 1]; + } + st[++k] = idx[i]; + top = k; + } + root = st[0]; + } +} ct; +bool cmp(int x, int y) { + return ct.key[x] < ct.key[y]; +} +int main() { + while (~scanf("%d", &n)) { + ct.init(); + for (int i = 1; i <= n; ++i) { idx[i] = i; } + sort(idx + 1, idx + n + 1, cmp); + ct.build(); + puts("YES"); + for (int i = 1; i <= n; ++i) { + printf("%d %d %d\n", ct.pre[i], ct.ch[i][0], ct.ch[i][1]); + } + } +} diff --git a/.ACM-Templates/TXTs/数据结构模板.txt b/.ACM-Templates/TXTs/数据结构模板.txt new file mode 100644 index 0000000..1e2e966 --- /dev/null +++ b/.ACM-Templates/TXTs/数据结构模板.txt @@ -0,0 +1,456 @@ +============ݽṹģ================ + +̬ +̬һҪάɭֵͨԵܳƣҪάij㵽ijЩݣ֧з֣ϲԼijЩнһijЩ򻯰棨IJĻݽṹLCT(link-cut tree) + +const int MAXN = 100010; +struct Node +{ + Node *ch[2], *p; + int size, value; + bool rev; + Node(int t = 0); + inline bool dir(void) + { + return p->ch[1] == this; + } + inline void SetC(Node *x, bool d) + { + ch[d] = x; + x->p = this; + } + inline void Rev(void) + { + swap(ch[0], ch[1]); + rev ^= 1; + } + inline void Push(void) + { + if (rev) + { + ch[0]->Rev(); + ch[1]->Rev(); + rev = 0; + } + } + inline void Update(void) + { + size = ch[0]->size + ch[1]->size + 1; + } +} Tnull, *null = &Tnull, *fim[MAXN]; +// ҪǵönullϢ +Node::Node(int _value) +{ + ch[0] = ch[1] = p = null; + rev = 0; +} +inline bool isRoot(Node *x) +{ + return x->p == null || (x != x->p->ch[0] && x != x->p->ch[1]); +} +inline void rotate(Node *x) +{ + Node *p = x->p; + bool d = x->dir(); + p->Push(); + x->Push(); + if (!isRoot(p)) p->p->SetC(x, p->dir()); + else x->p = p->p; + p->SetC(x->ch[!d], d); + x->SetC(p, !d); + p->Update(); +} +inline void splay(Node *x) +{ + x->Push(); + while (!isRoot(x)) + { + if (isRoot(x->p)) rotate(x); + else + { + if (x->dir() == x->p->dir()) + { + rotate(x->p); + rotate(x); + } + else + { + rotate(x); + rotate(x); + } + } + } + x->Update(); +} +inline Node* Access(Node *x) +{ + Node *t = x, *q = null; + for (; x != null; x = x->p) + { + splay(x); + x->ch[1] = q; + q = x; + } + splay(t); //info will be updated in the splay; + return q; +} +inline void Evert(Node *x) +{ + Access(x); + x->Rev(); +} +inline void link(Node *x, Node *y) +{ + Evert(x); + x->p = y; +} +inline Node* getRoot(Node *x) +{ + Node *tmp = x; + Access(x); + while (tmp->Push(), tmp->ch[0] != null) tmp = tmp->ch[0]; + splay(tmp); + return tmp; +} +// һҪȷxy֮б +inline void cut(Node *x, Node *y) +{ + Access(x); + splay(y); + if (y->p != x) swap(x, y); + Access(x); + splay(y); + y->p = null; +} +inline Node* getPath(Node *x, Node *y) +{ + Evert(x); + Access(y); + return y; +} +inline void clear(void) +{ + null->rev = 0; + null->sie = 0; + null->value = 0; +} + +splayģ壬Ϊ֣һΪsplayƽʹãڶΪsplay߶άʹáעÿInsert֮Ҫsplay䷵ֵ +// ܵĽڵ +const int MAXN = 100010; +// ÿǵIJǸڵϢȻӽڵ +struct Node +{ + Node *ch[2], *p; + int size, value; + bool rev; + inline bool dir(void) + { + return p->ch[1] == this; + } + inline void SetC(Node *x, bool d) + { + ch[d] = x; + x->p = this; + } + inline void Rev(void) + { + swap(ch[0], ch[1]); + rev ^= 1; + } + // nullԶpush + inline void Push(void) + { + if (rev) + { + ch[0]->Rev(); + ch[1]->Rev(); + rev = 0; + } + } + // nullԶupdate + inline void Update(void) + { + size = ch[0]->size + ch[1]->size + 1; + } + inline void initInfo(void) + { + rev = 0; + } +} Tnull, *null = &Tnull, *data, POOL[MAXN]; +class Splay +{ +public: + Node *root; + inline void rotate(Node *x) + { + Node *p = x->p; + bool d = x->dir(); + p->Push(); + x->Push(); + p->p->SetC(x, p->dir()); + p->SetC(x->ch[!d], d); + x->SetC(p, !d); + p->Update(); + } + inline void splay(Node *x, Node *G) + { + if (G == null) root = x; + while (x->p != G) + { + if (x->p->p == G) rotate(x); + else + { + if (x->dir() == x->p->dir()) + { + rotate(x->p); + rotate(x); + } + else + { + rotate(x); + rotate(x); + } + } + } + x->Push(); + x->Update(); + } + inline Node* Renew(int value) + { + Node *ret = data++; + ret->ch[0] = ret->ch[1] =ret->p = null; + ret->size = 1; + ret->value = value; + ret->initInfo(); + return ret; + } + inline Node* getMin(Node *x) + { + Node *tmp = x; + while (tmp->ch[0] != null) tmp = tmp->ch[0]; + return tmp; + } + inline Node* getMax(Node *x) + { + Node *tmp = x; + while (tmp->ch[1] != null) tmp = tmp->ch[1]; + return tmp; + } + // ѯk + inline Node* getKth(int k) + { + Node *tmp = root; + assert(k > 0 && k <= root->size); + while (true) + { + tmp->Push(); + if (tmp->ch[0]->size + 1 == k) return tmp; + if (tmp->ch[0]->size >= k) tmp = tmp->ch[0]; + else k -= tmp->ch[0]->size + 1, tmp = tmp->ch[1]; + } + } + // Ϊsplayƽʹ + // value = vԪ, ֮splay + inline Node* find(int v) + { + Node *tmp = root; + while (tmp != null) + { + tmp->Push(); + if (tmp->value == v) return tmp; + if (v < tmp->value) tmp = tmp->ch[0]; + else tmp = tmp->ch[1]; + } + return null; + } + // ͳжԪСڵv, flag = 1ʱͳƶԪϸСv, һҪǵsplayǸtmp + inline int Count(int v, bool flag = 0) + { + Node *tmp = root, *last = null; + int ret = 0; + while (tmp != null) + { + tmp->Push(); + last = tmp; + if ((!flag && tmp->value > v) || (flag && tmp->value >= v)) + { + tmp = tmp->ch[0]; + } + else ret += tmp->ch[0]->size + 1, tmp = tmp->ch[1]; + } + if (last != null) splay(last, null); + return ret; + } + // ɾx + inline void erase(Node* x) + { + splay(x, null); + if (x->ch[0] == null || x->ch[1] == null) + { + int d = x->ch[1] != null; + root = x->ch[d]; + root->p = null; + return; + } + Node *L = getMax(x->ch[0]), *R = getMax(x->ch[1]); + splay(L, x); + splay(R, x); + L->SetC(R, 1); + L->p = null; + root = L; + L->Update(); + } + // һֵΪvalueĽڵ㣬ʼҪInsert(root, null, value), ֮splay + inline Node* Insert(Node *&now, Node* father, int value) + { + if (now == null) + { + now = Renew(value); + now->p = father; + return now; + } + Node *ret; + now->Push(); + if (value <= now->value) ret = Insert(now->ch[0], now, value); + else ret = Insert(now->ch[1], now, value); + now->Update(); + return ret; + } + // Ϊsplayά, ʼҪԭзһ-infinfֹ߽ + // õԭ[l,r]ӦĽ㣬l == r + 1ʾһ + inline Node* getInterval(int l, int r) + { + assert(l <= r + 1); + Node *L = getKth(l), *R = getKth(r + 2); + splay(L, null); + splay(R, L); + return R->ch[0]; + } + // ɾһ[l,r] + inline void eraseInterval(int l, int r) + { + getInterval(l, r); + root->ch[1]->ch[0] = null; + root->ch[1]->Update(); + root->Update(); + } + // λlĺһx (0 <= l <= n) + inline void insertInterval(int l, Node *x) + { + Node *L = getKth(l + 1), *R = getKth(l + 2); + splay(L, null); + splay(R, L); + R->SetC(x, 0); + R->Update(); + L->Update(); + } + // a[l,r]Ϊһsplay + inline Node* Build(int l, int r, int a[]) + { + if (l > r) return null; + int mid = (l + r) >> 1; + Node *ret = Renew(a[mid]); + if (l == r) return ret; + ret->SetC(Build(l, mid - 1, a), 0); + ret->SetC(Build(mid + 1, r, a), 1); + ret->Update(); + return ret; + } +} T; +void clear(void) +{ + data = POOL; + T.root = null; +} + +㷨׺飬ʱ临ӶΪ $O(n \lg n)$. עַյĺ׺ 1 ʼ. Ҫַ֤жΪ0ַ, ַĵn+1λӦΪ0. +// string is 1-base, sa is 1-base +int w[MAXM]; +inline void Sort(int a[], int ret[], int n, int m = MAXM - 1) +{ + for (int i = 0; i <= m; i++) w[i] = 0; + for (int i = 1; i <= n; i++) w[a[i]]++; + for (int i = 1; i <= m; i++) w[i] += w[i - 1]; + for (int i = n; i >= 1; i--) ret[w[a[i]]--] = i; +} +int wa[MAXN], wb[MAXN], tmp[MAXN]; +inline void getSA(int ch[], int sa[], int n) +{ + int *x = wa, *y = wb; + for (int i = 1; i <= n; i++) x[i] = ch[i]; + Sort(ch, sa, n); + for (int j = 1, p = 1, m = MAXN - 1; p < n; m = p, j <<= 1) + { + p = 0; + for (int i = n - j + 1; i <= n; i++) y[++p] = i; + for (int i = 1; i <= n; i++) if (sa[i] > j) y[++p] = sa[i] - j; + for (int i = 1; i <= n; i++) tmp[i] = x[y[i]]; + Sort(tmp, sa, n, m); + for (int i = 1; i <= n; i++) sa[i] = y[sa[i]]; + swap(x, y); + x[sa[1]] = p = 1; + for (int i = 2; i <= n; i++) + { + if (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j]) x[sa[i]] = p; + else x[sa[i]] = ++p; + } + } + sa[0] = n + 1; // for calculate height. +} +int rank[MAXN]; +inline void getHeight(int ch[], int sa[], int height[], int n) +{ + for (int i = 1; i <= n; i++) rank[sa[i]] = i; + for (int i = 1, t = 0; i <= n; i++) + { + if (t > 0) t--; + while (ch[i + t] == ch[sa[rank[i] - 1] + t]) t++; + height[rank[i]] = t; + } +} + +׺ԶͳһֵĴʱֻͳڵӦУendΪtrueĽڵĸɡнڵ㰴valֵС󼴿ɵõparentɸʼBFS + +struct Node +{ + Node *next[26], *par; + int val, end; // 26 is volatile +} POOL[MAXN << 1], *data, *root, *last; //Note that the size of POOL should be doubled. +inline void Add(int x) +{ + Node *p = last, *np = data++; + np->val = p->val + 1; + np->end = true; + while (p && !p->next[x]) + p->next[x] = np, p = p->par; + if (p == 0) + { + np->par = root; + } + else + { + Node *q = p->next[x]; + if (q->val == p->val + 1) + { + np->par = q; + } + else + { + Node *nq = data++; + nq->val = p->val + 1; + memcpy(nq->next, q->next, sizeof q->next); + nq->par = q->par; + np->par = q->par = nq; + while (p && p->next[x] == q) + p->next[x] = nq, p = p->par; + } + } + last = np; +} +void Clear(void) +{ + data = POOL; + last = root = data++; +} + diff --git a/.ACM-Templates/TXTs/数论模板.txt b/.ACM-Templates/TXTs/数论模板.txt new file mode 100644 index 0000000..0ef53ee --- /dev/null +++ b/.ACM-Templates/TXTs/数论模板.txt @@ -0,0 +1,825 @@ +===============ѧģ=========== +㼸ģ壬 +\begin{itemize} +\item point2/3 /+-**%ģdisarg2άתrotate2άƽparallelֱperpendάķһͶӰΪάԼͶӰ +\item line2/3 ߣʾΪ+߾ʹ㣬߽߶߶ν߶ν˻2ά߾ԣ3άƽзһԣߵͶӰͬ㣩 +\item face3 棬ʾΪ+ʹ㣬潻潻 +\item circle2 ԲʾΪԲ+뾶ԲԲԲ㵽Բе㣬ԲԲĹߣе㣬ֱ˵Ϊе㣬򷵻ֱ߶˵Ϊе㣩 +\item convex2 ͹㲻ϸ͹ڣ͹ˮƽGraham͹ƽ潻ƽΪƽ棩 +\end{itemize} +˵Ҫ/ߵģ/Ϊָ봫룬ΪNULLʾҪĬϣҪ/߸ģֵΪ-1ʾ + + +#include +#include +#include +#include +#include +const double eps = 1e-13; +const double pi = 3.14159265358979324; +struct point2 +{ + double x, y; + point2& operator += (point2 a) + { + x+=a.x, y+=a.y; + return *this; + } + point2& operator -= (point2 a) + { + x-=a.x, y-=a.y; + return *this; + } + point2& operator *= (double a) + { + x*=a, y*=a; + return *this; + } + point2& operator /= (double a) + { + x/=a, y/=a; + return *this; + } +}; +point2 operator + (point2 a, point2 b) +{ + point2 c(a); + c += b; + return c; +} +point2 operator - (point2 a, point2 b) +{ + point2 c(a); + c -= b; + return c; +} +point2 operator * (point2 a, double b) +{ + point2 c(a); + c *= b; + return c; +} +point2 operator * (double a, point2 b) +{ + point2 c(b); + c *= a; + return c; +} +point2 operator / (point2 a, double b) +{ + point2 c(a); + c /= b; + return c; +} +double operator * (point2 a, point2 b) +{ + return a.x*b.x+a.y*b.y; +} +double operator % (point2 a, point2 b) +{ + return a.x*b.y-a.y*b.x; +} +double dis(point2 a) +{ + return sqrt(a.x * a.x + a.y * a.y); +} +double arg(point2 a) +{ + return atan2(a.y, a.x); +} +point2 rotate(point2 a, double th) +{ + point2 b; + b.x = a.x * cos(th) - a.y * sin(th); + b.y = a.x * sin(th) + a.y * cos(th); + return b; +} +int parallel(point2 a, point2 b) +{ + return a * a < eps * eps || b * b < eps * eps + || (a % b) * (a % b) / ((a * a) * (b * b)) < eps * eps; +} +int perpend(point2 a, point2 b) +{ + return a * a < eps * eps || b * b < eps * eps + || (a * b) * (a * b) / ((a * a) * (b * b)) < eps * eps; +} +struct line2 +{ + point2 a, s; +}; +struct circle2 +{ + point2 a; + double r; +}; +double point_line_dis(point2 a, line2 b, point2 *res = NULL) +{ + point2 p; + p = b.a + ((a - b.a) * b.s) / (b.s * b.s) * b.s; + if (res != NULL) *res = p; + return dis(a - p); +} +int line_line_cross(line2 a, line2 b, point2 *res = NULL) +{ + if (parallel(a.s, b.s)) + if (parallel(b.a - a.a, a.s)) + return -1; + else + return 0; + double k1 = (b.a - a.a) % b.s / (a.s % b.s); + if (res != NULL) *res = a.a + k1 * a.s; + return 1; +} +int segment_segment_cross(line2 a, line2 b, point2 *res = NULL) +{ + if (a.s * a.s < eps * eps && b.s * b.s < eps * eps) + if ((b.a - a.a) * (b.a - a.a) < eps * eps) + { + if (res != NULL) *res = a.a; + return 1; + } + else + return 0; + if (parallel(a.s, b.s) && parallel(b.a - a.a, a.s) && parallel(a.a - b.a, b.s)) + { + double y1, y2, y3, y4; + point2 y1p = a.a, y2p = a.a + a.s, y3p = b.a, y4p = b.a + b.s; + if (std::abs(a.s.x) < std::abs(a.s.y) || std::abs(b.s.x) < std::abs(b.s.y)) + y1 = y1p.y, y2 = y2p.y, y3 = y3p.y, y4 = y4p.y; + else + y1 = y1p.x, y2 = y2p.x, y3 = y3p.x, y4 = y4p.x; + if (y1 > y2) std::swap(y1, y2), std::swap(y1p, y2p); + if (y3 > y4) std::swap(y3, y4), std::swap(y3p, y4p); + if (y2 - y1 < y4 - y3) std::swap(y1, y3), std::swap(y1p, y3p), std::swap(y2, y4), std::swap(y2p, y4p); + if (y3 > y2 + (y2 - y1) * eps || y4 < y1 - (y2 - y1) * eps) + return 0; + else if (fabs(y3 - y2) < (y2 - y1) * eps || fabs(y3 - y4) < eps) + { + if (res != NULL) *res = y3p; + return 1; + } + else if (fabs(y4 - y1) < (y2 - y1) * eps || fabs(y1 - y2) < eps) + { + if (res != NULL) *res = y1p; + return 1; + } + else + return -1; + } + else + { + double k1 = (b.a - a.a) % a.s, k2 = (b.a + b.s - a.a) % a.s; + k1 /= a.s * a.s, k2 /= a.s * a.s; + double k3 = (a.a - b.a) % b.s, k4 = (a.a + a.s - b.a) % b.s; + k3 /= b.s * b.s, k4 /= b.s * b.s; + int ret = (k1 < eps && k2 > -eps || k1 > -eps && k2 < eps) + && (k3 < eps && k4 > -eps || k3 > -eps && k4 < eps); + if (ret) line_line_cross(a, b, res); + return ret; + } +} +int line_circle_cross(line2 a, circle2 b, point2 *res1 = NULL, point2 *res2 = NULL) +{ + point2 p; + double d = point_line_dis(b.a, a, &p); + if (d / b.r > 1 + eps) + return 0; + else if (d / b.r > 1 - eps) + { + if (res1 != NULL) *res1 = p; + return 1; + } + else + { + d = sqrt(b.r * b.r - d * d) / dis(a.s); + if (res1 != NULL) *res1 = p + d * a.s; + if (res2 != NULL) *res2 = p - d * a.s; + return 2; + } +} +int circle_circle_cross(circle2 a, circle2 b, point2 *res1 = NULL, point2 *res2 = NULL) +{ + double d = dis(a.a - b.a); + point2 u = (b.a - a.a) / d; + if (d / (a.r + b.r) > 1 + eps) + return 0; + else if (d / (a.r + b.r) > 1 - eps) + { + if (res1 != NULL) *res1 = a.a + u * a.r; + return 1; + } + else if ((d - fabs(a.r - b.r)) / (a.r + b.r) > eps) + { + double th = acos((a.r * a.r + d * d - b.r * b.r) / (2 * a.r * d)); + if (res1 != NULL) *res1 = a.a + rotate(u * a.r, th); + if (res2 != NULL) *res2 = a.a + rotate(u * a.r, -th); + return 2; + } + else if ((d - fabs(a.r - b.r)) / (a.r + b.r) > -eps) + { + if (a.r / b.r < 1 - eps) + { + if (res1 != NULL) *res1 = b.a - u * b.r; + return 1; + } + else if (a.r / b.r > 1 + eps) + { + if (res1 != NULL) *res1 = a.a + u * a.r; + return 1; + } + else return -1; + } + else + return 0; +} +int point_circle_tangent(point2 a, circle2 b, point2 *res1 = NULL, point2 *res2 = NULL) +{ + double d = dis(a - b.a); + point2 u = (a - b.a) / d; + if (d / b.r > 1 + eps) + { + double th = acos(b.r / d); + if (res1 != NULL) *res1 = b.a + rotate(u * b.r, th); + if (res2 != NULL) *res2 = b.a + rotate(u * b.r, -th); + return 2; + } + else if (d / b.r > 1 - eps) + { + if (res1 != NULL) *res1 = a; + return 1; + } + else + return 0; +} +int circle_circle_tangent(circle2 a, circle2 b, line2 *reso1 = NULL, line2 *reso2 = NULL, line2 *resi1 = NULL, line2 *resi2 = NULL) +{ + double d = dis(a.a - b.a); + point2 u = (b.a - a.a) / d; + int cnt = 0; + if ((d - fabs(a.r - b.r)) / (a.r + b.r) > eps) + { + double th = acos((a.r - b.r) / d); + if (reso1 != NULL) + { + reso1->a = a.a + rotate(u * a.r, th); + reso1->s = b.a + rotate(u * b.r, th) - reso1->a; + } + if (reso2 != NULL) + { + reso2->a = a.a + rotate(u * a.r, -th); + reso2->s = b.a + rotate(u * b.r, -th) - reso2->a; + } + cnt += 2; + } + else if ((d - fabs(a.r - b.r)) / (a.r + b.r) > -eps) + { + if (a.r / b.r < 1 - eps) + { + if (reso1 != NULL) + { + reso1->a = b.a - u * b.r; + reso1->s = rotate(u, pi / 2); + } + cnt++; + } + else if (a.r / b.r > 1 + eps) + { + if (reso1 != NULL) + { + reso1->a = a.a + u * a.r; + reso1->s = rotate(u, pi / 2); + } + cnt++; + } + else return -1; + } + if (d / (a.r + b.r) > 1 + eps) + { + double th = acos((a.r + b.r) / d); + if (resi1 != NULL) + { + resi1->a = a.a + rotate(u * a.r, th); + resi1->s = b.a - rotate(u * b.r, th) - resi1->a; + } + if (resi2 != NULL) + { + resi2->a = a.a + rotate(u * a.r, -th); + resi2->s = b.a - rotate(u * b.r, -th) - resi2->a; + } + cnt += 2; + } + else if (d / (a.r + b.r) > 1 - eps) + { + if (resi1 != NULL) + { + resi1->a = a.a + u * a.r; + resi1->s = rotate(u, pi / 2); + } + cnt++; + } + return cnt; +} +typedef std::vector convex2; +double area(const convex2 &a) +{ + double s = 0; + for (int i = 0; i < a.size(); i++) + s += a[i] % a[(i+1)%a.size()]; + return fabs(s)/2; +} +int point_convex_inside(point2 a, const convex2 &b) +{ + double sum = 0; + for (int i = 0; i < b.size(); i++) + sum += fabs((b[i] - a) % (b[(i+1)%b.size()] - a)); + return fabs(sum / (2*area(b)) - 1) < eps; +} +int line_convex_cross(line2 a, const convex2 &b, point2 *res1 = NULL, point2 *res2 = NULL) +{ + int cnt = 0; + for (int i = 0; i < b.size(); i++) + { + line2 ltmp; + point2 ptmp; + ltmp.a = b[i], ltmp.s = b[(i+1)%b.size()] - b[i]; + int flag = line_line_cross(a, ltmp, &ptmp); + if (flag == -1) return -1; + if (flag == 0) continue; + double k = (ptmp - ltmp.a) * ltmp.s / (ltmp.s * ltmp.s); + if (k < eps || k > 1+eps) continue; + if (cnt == 0 && res1 != NULL) *res1 = ptmp; + else if (cnt == 1 && res2 != NULL) *res2 = ptmp; + cnt++; + } + return cnt; +} +int convex_gen_cmp(point2 a, point2 b) +{ + return a.y < b.y - eps || fabs(a.y - b.y) < eps && a.x < b.x - eps; +} +int convex_gen(const convex2 &a, convex2 &b) +{ + std::deque q; + convex2 t(a); + std::sort(t.begin(), t.end(), convex_gen_cmp); + q.push_back(t[0]), q.push_back(t[1]); + for (int i = 2; i < t.size(); i++) + { + while (q.size() > 1) + { + point2 p1 = t[i]-q[q.size()-1], p2 = q[q.size()-1]-q[q.size()-2]; + if (p1 % p2 > 0 || parallel(p1, p2)) q.pop_back(); + else break; + } + q.push_back(t[i]); + } + int pretop = q.size(); + for (int i = t.size()-1; i >= 0; i--) + { + while (q.size() > pretop) + { + point2 p1 = t[i]-q[q.size()-1], p2 = q[q.size()-1]-q[q.size()-2]; + if (p1 % p2 > 0 || parallel(p1, p2)) q.pop_back(); + else break; + } + q.push_back(t[i]); + } + q.pop_back(); + if (q.size() < 3) + { + b.clear(); + return 0; + } + b.clear(); + for (int i = 0; i < q.size(); i++) b.push_back(q[i]); + return 1; +} +int halfplane_cross_cmp(line2 a, line2 b) +{ + double c1 = arg(a.s), c2 = arg(b.s); + return c1 < c2-eps || fabs(c1-c2) < eps && b.s % (a.a - b.a) / dis(b.s) > eps; +} +int halfplane_cross(const std::vector &a, convex2 &b) +{ + std::vector t(a); + std::sort(t.begin(), t.end(), halfplane_cross_cmp); + int j = 0; + for (int i = 0; i < t.size(); i++) + if (!i || arg(t[i].s) > arg(t[i-1].s) + eps) t[j++] = t[i]; + if (j > 0 && arg(t[j].s) > arg(t[0].s) + 2*pi - eps) j--; + t.resize(j); + std::deque q; + q.push_back(t[0]), q.push_back(t[1]); + point2 p; + for (int i = 2, k = 0; i < t.size(); i++) + { + for (; k < q.size() && t[i].s % q[k].s > 0; k++); + point2 s1 = q[q.size()-1].s, s2 = q[0].s; + if (k > 0 && k < q.size() && s1 % s2 > 0 && !parallel(s1, s2)) + { + line_line_cross(q[k], q[k-1], &p); + double r1 = t[i].s % (p - t[i].a) / dis(t[i].s); + line_line_cross(q[0], q[q.size()-1], &p); + double r2 = t[i].s % (p - t[i].a) / dis(t[i].s); + if (r1 < eps && r2 < eps) + { + b.clear(); + return 0; + } + else if (r1 > -eps && r2 > -eps) + continue; + } + while (q.size() > 1) + { + line_line_cross(q[q.size()-1], q[q.size()-2], &p); + if (t[i].s % (p - t[i].a) / dis(t[i].s) < eps) + { + q.pop_back(); + if (k == q.size()) k--; + } + else break; + } + while (q.size() > 1) + { + line_line_cross(q[0], q[1], &p); + if (t[i].s % (p - t[i].a) / dis(t[i].s) < eps) + { + q.pop_front(); + k--; + if (k < 0) k = 0; + } + else break; + } + q.push_back(t[i]); + } + b.clear(); + for (int i = 0; i < q.size(); i++) + { + line_line_cross(q[i], q[(i+1)%q.size()], &p); + b.push_back(p); + } + return 1; +} +struct point3 +{ + double x, y, z; + point3& operator += (point3 a) + { + x+=a.x,y+=a.y,z+=a.z; + return *this; + } + point3& operator -= (point3 a) + { + x-=a.x,y-=a.y,z-=a.z; + return *this; + } + point3& operator *= (double a) + { + x*=a, y*=a, z*=a; + return *this; + } + point3& operator /= (double a) + { + x/=a, y/=a, z/=a; + return *this; + } +}; +point3 operator + (point3 a, point3 b) +{ + point3 c(a); + c += b; + return c; +} +point3 operator - (point3 a, point3 b) +{ + point3 c(a); + c -= b; + return c; +} +point3 operator * (point3 a, double b) +{ + point3 c(a); + c *= b; + return c; +} +point3 operator * (double a, point3 b) +{ + point3 c(b); + c *= a; + return c; +} +point3 operator / (point3 a, double b) +{ + point3 c(a); + c /= b; + return c; +} +double operator * (point3 a, point3 b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z; +} +point3 operator % (point3 a, point3 b) +{ + point3 c; + c.x = a.y * b.z - a.z * b.y; + c.y = a.z * b.x - a.x * b.z; + c.z = a.x * b.y - a.y * b.x; + return c; +} +double dis(point3 a) +{ + return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); +} +int parallel(point3 a, point3 b) +{ + return a * a < eps * eps || b * b < eps * eps + || (a % b) * (a % b) / ((a * a) * (b * b)) < eps * eps; +} +int perpend(point3 a, point3 b) +{ + return a * a < eps * eps || b * b < eps * eps + || (a * b) * (a * b) / ((a * a) * (b * b)) < eps * eps; +} +struct line3 +{ + point3 a, s; +}; +struct face3 +{ + point3 a, n; +}; +struct circle3 +{ + point3 a; + double r; +}; +point2 project(point3 a, face3 b, point3 xs) +{ + point3 ys; + ys = b.n % xs; + point2 c; + c.x = ((a - b.a) * xs) / dis(xs), c.y = ((a - b.a) * ys) / dis(ys); + return c; +} +line2 project(line3 a, face3 b, point3 xs) +{ + line2 c; + c.a = project(a.a, b, xs), c.s = project(a.a + a.s, b, xs) - c.a; + return c; +} +point3 revproject(point2 a, face3 b, point3 xs) +{ + point3 ys; + ys = b.n % xs; + return a.x * xs / dis(xs) + a.y * ys / dis(ys) + b.a; +} +line3 revproject(line2 a, face3 b, point3 xs) +{ + line3 c; + c.a = revproject(a.a, b, xs), c.s = revproject(a.a + a.s, b, xs) - c.a; + return c; +} +double point_line_dis(point3 a, line3 b, point3 *res = NULL) +{ + point3 p; + p = b.a + ((a - b.a) * b.s) / (b.s * b.s) * b.s; + if (res != NULL) *res = p; + return dis(a - p); +} +double point_face_dis(point3 a, face3 b, point3 *res = NULL) +{ + point3 p; + p = ((a - b.a) * b.n) / (b.n * b.n) * b.n; + if (res != NULL) *res = a - p; + return dis(p); +} +double line_line_dis(line3 a, line3 b, point3 *resa = NULL, point3 *resb = NULL) +{ + point3 p; + if (parallel(a.s, b.s)) + { + double d = point_line_dis(a.a, b, &p); + if (resa != NULL) *resa = a.a; + if (resb != NULL) *resb = p; + return d; + } + point3 n = a.s % b.s; + face3 f; + f.a = b.a, f.n = n; + double d = point_face_dis(a.a, f, &p); + double k1 = ((b.a - p) % b.s) * n / (n * n); + if (resb != NULL) *resb = p + k1 * a.s; + if (resa != NULL) *resa = a.a + k1 * a.s; + return d; +} +int line_face_cross(line3 a, face3 b, point3 *res = NULL) +{ + if (perpend(a.s, b.n)) + if (perpend(b.a - a.a, b.n)) + return -1; + else + return 0; + double k = (b.a - a.a) * b.n / (a.s * b.n); + if (res != NULL) *res = a.a + k * a.s; + return 1; +} +int face_face_cross(face3 a, face3 b, line3 *res = NULL) +{ + if (parallel(a.n, b.n)) + if (perpend(b.a - a.a, a.n)) + return -1; + else + return 0; + point3 s = a.n % b.n; + point3 p; + line3 t; + t.a = a.a, t.s = a.n % s; + line_face_cross(t, b, &p); + if (res != NULL) + res->a = p, res->s = s; + return 1; +} + +=============ģ========== +ģ壬а +\begin{itemize} +\item ext\_gcdչŷ÷ $ax+by=\gcd(a,b)$ú֤ $a,b>0$ ʱ $x>0$ +\item flsumŷ˼ $\sum_{x=st}^{ed}\lfloor\frac{ax+b}c\rfloor$ +\item indС㷨 $a^x=m\pmod b$ +\item prepare\_inv$O(p)$ ģ $p$ зԪԪ$p$ +\end{itemize} + +#include +#include +#include +#include +#include +void ext_gcd(int a, int b, int &x, int &y) +{ + if (!b) x = 1, y = 0; + else if (!a) x = 1, y = -1; + else if (a > b) ext_gcd(a % b, b, x, y), y += a / b * x; + else ext_gcd(a, b % a, x, y), x += b / a * y; +} +long long flsum_t (long long a, long long b, long long c, long long n) +{ + if (n < 0) return 0; + if (c < 0) a = -a, b = -b, c = -c; + n++; + long long res = 0; + if (a < 0 || a >= c) + { + long long ra = (a % c + c) % c; + long long k = (a - ra) / c; + res += k * n * (n - 1) / 2; + a = ra; + } + if (b < 0 || b >= c) + { + long long rb = (b % c + c) % c; + long long k = (b - rb) / c; + res += k * n; + b = rb; + } + if (a * n + b < c) return res; + else return res + flsum_t(c, (a * n + b) % c, a, (a * n + b) / c - 1); +} +long long flsum (long long a, long long b, long long c, long long st, long long ed) +{ + return flsum_t(a, b, c, ed) - flsum_t(a, b, c, st - 1); +} +int power(int n, int k, int r) +{ + int t = n, s = 1; + for (; k; k >>= 1, t = 1LL * t * t % r) + if (k & 1) s = 1LL * s * t % r; + return s; +} +int millerrabin(int x, int tester) +{ + int k = x-1; + for (; !(k & 1); k >>= 1); + int y = power(tester, k, x); + if (y == 1) return 1; + for (; k < x-1; k <<= 1, y = 1LL * y * y % x) + if (y == x-1) return 1; + return 0; +} +int isprime(int x) +{ + if (x == 2 || x == 7 || x == 61) return 1; + return millerrabin(x, 2) && millerrabin(x, 7) && millerrabin(x, 61); +} +int rho_f(int x, int c, int p) +{ + return (1LL * x * x + c) % p; +} +int rho(int n) +{ + int c = rand() % (n-1) + 1, x = 2, y = x, d = 1; + while (d == 1) + { + x = rho_f(x, c, n); + y = rho_f(rho_f(y, c, n), c, n); + d = std::__gcd(y > x ? y-x : x-y, n); + } + return d; +} +void factor(int n, std::vector &res) +{ + if (n == 1) return; + else if (isprime(n)) res.push_back(n); + else if (n == 4) res.push_back(2), res.push_back(2); + else + { + int d; + while ((d = rho(n)) == n); + factor(d, res), factor(n / d, res); + } +} +int ind(int a, int b, int m) +{ + a %= m, b %= m; + std::map hash; + int r = (int)(sqrt(m)), k = 1; + if (r * r < m) r++; + for (int i = 0; i < r; i++, k = 1LL * k * a % m) + if (hash.find(k) == hash.end()) + hash.insert(std::make_pair(k, i)); + int s = 1; + std::map::iterator it; + for (int i = 0; i < r; i++, s = 1LL * s * k % m) + { + int x, y, t; + ext_gcd(s, m, x, y); + t = 1LL * b * x % m; + if ((it = hash.find(t)) != hash.end()) + return i * r + it->second; + } +} +void prepare_inv(int *inv, int p) +{ + inv[1] = 1; + for (int i = 2; i < p; i++) + inv[i] = 1LL * inv[p%i] * (p - p/i) % p; +} + + +=================ֵ============= +ֵģ壬ں +\begin{itemize} +\item area\_simpsonSimpson󶨻֡ +\item fft\_prepare $maxn$ ελָ +\item dftΪ $N(N|maxn)$ DFT $f=-1$ IDFT +\end{itemize} + +#include +#include +#include +const double pi = 3.14159265358979324; +typedef double (*__F) (double); +double area(double x, double y, double fl, double fmid, double fr) +{ + return (fl + 4 * fmid + fr) * (y - x) / 6; +} +double area_simpson_solve(__F f, double x, double mid, double y, double fl, double fmid, double fr, double pre, double zero) +{ + double lmid = (x + mid) / 2, rmid = (mid + y) / 2; + double flmid = f(lmid), frmid = f(rmid); + double al = area(x, mid, fl, flmid, fmid), ar = area(mid, y, fmid, frmid, fr); + if (fabs(al + ar - pre) < zero) return al + ar; + else return area_simpson_solve(f, x, lmid, mid, fl, flmid, fmid, al, zero) + area_simpson_solve(f, mid, rmid, y, fmid, frmid, fr, ar, zero); +} +double area_simpson(__F f, double x, double y, double zero = 1e-10) +{ + double mid = (x + y) / 2, fl = f(x), fmid = f(mid), fr = f(y); + return area_simpson_solve(f, x, mid, y, fl, fmid, fr, area(x, y, fl, fmid, fr), zero); +} +typedef std::complex complex; +void fft_prepare(int maxn, complex *&e) +{ + e = new complex[2 * maxn - 1]; + e += maxn - 1; + e[0] = complex(1, 0); + for (int i = 1; i < maxn; i <<= 1) + e[i] = complex(cos(2 * pi * i / maxn), sin(2 * pi * i / maxn)); + for (int i = 3; i < maxn; i++) + if ((i & -i) != i) e[i] = e[i - (i & -i)] * e[i & -i]; + for (int i = 1; i < maxn; i++) e[-i] = e[maxn - i]; +} +/* f = 1: dft; f = -1: idft */ +void dft(complex *a, int N, int f, complex *e, int maxn) +{ + int d = maxn / N * f; + complex x; + for (int n = N, m; m = n / 2, m >= 1; n = m, d *= 2) + for (int i = 0; i < m; i++) + for (int j = i; j < N; j += n) + x = a[j] - a[j+m], a[j] += a[j+m], a[j+m] = x * e[d * i]; + for (int i = 0, j = 1; j < N - 1; j++) + { + for (int k = N / 2; k > (i ^= k); k /= 2); + if (j < i) std::swap(a[i], a[j]); + } +} diff --git a/.ACM-Templates/TXTs/日期.txt b/.ACM-Templates/TXTs/日期.txt new file mode 100644 index 0000000..afa564e --- /dev/null +++ b/.ACM-Templates/TXTs/日期.txt @@ -0,0 +1,47 @@ +//ں +char *week[] = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}; +int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +struct Date { int y, m, d; }; +// +inline int leap(int y) { + return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; +} +//кϷ +inline bool legal(Date &a) { + if (a.m < 0 || a.m > 12) { return false; } + if (a.m == 2) { return a.d > 0 && a.d <= 28 + leap(a.y); } + return a.d > 0 && a.d <= days[a.m - 1]; +} +//ȽڴС +inline int datecmp(Date &a, Date &b) { + if (a.y != b.y) { return a.y - b.y; } + if (a.m != b.m) { return a.m - b.m; } + return a.d - b.d; +} +//ָڼ +int DaysOfTheWeek(Date a) { + if (a.m == 1 || a.m == 2) { a.m += 12; a.y--; } //12µǰһ13, 14 + //жǷ175293֮ǰ + if (a.y < 1752 || (a.y == 1752 && a.m < 9) || (a.y == 1752 && a.m == 9 && a.d < 3)) { + return (a.d + 2 * a.m + 3 * (a.m + 1) / 5 + a.y + a.y / 4 + 5) % 7; + } else { + return (a.d + 2 * a.m + 3 * (a.m + 1) / 5 + a.y + a.y / 4 - a.y / 100 + a.y / 400) % 7; + } +} +//תƫ +int date2int(Date a) { + int ret = a.y * 365 + (a.y - 1) / 4 - (a.y - 1) / 100 + (a.y - 1) / 400; + days[1] += leap(a.y); + for (int i = 0; i < a.m - 1; ret += days[i++]); + days[1] = 28; + return ret + a.d; +} +//ƫת +Date int2date(int a) { + Date ret; ret.y = a / 146097 * 400; + for (a %= 146097; a >= 365 + leap(ret.y); a -= 365 + leap(ret.y), ret.y++); + days[1] += leap(ret.y); + for (ret.m = 1; a >= days[ret.m - 1]; a -= days[ret.m - 1], ret.m++); + days[1] = 28; ret.d = a + 1; + return ret; +} diff --git a/.ACM-Templates/TXTs/混合模板.txt b/.ACM-Templates/TXTs/混合模板.txt new file mode 100644 index 0000000..e0732c2 --- /dev/null +++ b/.ACM-Templates/TXTs/混合模板.txt @@ -0,0 +1,772 @@ +==================ģ================ + +============ģ壨ȫ============== +#if __cplusplus >= 201103L +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +typedef long long ll; +const int N = 100005; +const int M = 1000000007; + +int n, m; +int a[N]; + +int main() { + int C = 0, T; + scanf("%d", &T); + while (++C <= T) { + scanf("%d", &n); + for (int i = 0; i < n; i++) { + scanf("%d", &a[i]); + } + + } +} + +===============ģ壨С=============== +#include +using namespace std; + +typedef long long ll; +const int N = 100005; +const int M = 1000000007; + +int n, m; +int a[N]; + +int main() { + while (~scanf("%d", &n)) { + for (int i = 0; i < n; i++) { + scanf("%d", &a[i]); + } + + } +} + + +=============================== +// Wizov game +//ѸɸƷ, ijһѻͬʱȡͬƷ, 涨ÿȡһ, ߲, ȡߵʤ +//ak = [k(1 + 5) / 2], bk = ak + k (k = 0, 1, 2, ..., n űʾȡ) +const double gs = (sqrt(5.0) + 1.0) / 2.0; +bool Wizov(ll a, ll b) { + return min(a, b) == (ll)(abs(a - b) * gs); +} +// 1 <= N <= 1e18 +const int N = 95; //~95 for 1e18 +ll fib[N] = { 0, 1 }; //Ԥfibonacci +bool s[N]; +bool Wizov(ll a, ll b) { + int w = upper_bound(fib + 1, fib + N, a) - fib - 1, pos = 1; ll ret = 0; + for (int i = w; i > 0; i--) { + if (a >= fib[i]) { s[i] = true; a -= fib[i]; } + else { s[i] = false; } + } + while (!s[pos]) { pos++; } + for (int i = pos & 1 ? w - 2 : w; i >= 0; i--) { + if (s[i]) { ret += fib[i + 1]; } + } + return ret == b; +} +//ķ Nimm Game +//ѸɸƷ, ijһȡƷ, 涨ÿȡһ, ߲, ȡߵʤ +//1 - nΧڵSGֵ +//Array洢ߵIJ, Array[0]ʾж߷ +//Array[]ҪС +//HDU1847 SG +//1.ѡΪ1-mֱȡģɣSG(x) = x % (m + 1); (ʲ Bash game) +//2.ѡΪⲽSG(x) = x; +//3.ѡΪһϵвSG(x) +int sg[N]; +bool Hash[N]; +int SG(int Array[], int n) { + memset(sg, 0, sizeof(sg)); + for (int i = 0; i <= n; ++i) { + memset(Hash, 0, sizeof(Hash)); + for (int j = 1; j <= Array[0]; j++) { + if (i < Array[j]) { break; } + Hash[sg[i - Array[j]]] = true; + } + for (int j = 0; j <= n; j++) { + if (!Hash[j]) { sg[i] = j; break; } + } + } + return sg[n]; +} +// +int a[N], ans[N][2]; //a[]Ϊʯ +void printNim(int n) { //ʯӶ + int cnt = 0, ret = 0; + for (int i = 0; i < n; i++) { ret ^= a[i]; } + for (int i = 0; i < n; i++) { + if (a[i] > (ret ^ a[i])) { + ans[cnt][0] = a[i]; ans[cnt][1] = s ^ a[i]; + cnt++; + } + } + if (cnt) { //жʤǸ + puts("Yes"); + printf("%d\n", cnt); //ʹΪʤķĿ + for (int i = 0; i < cnt; i++) { + printf("%d %d\n", ans[i][0], ans[i][1]); //Ϊʤ߷ + } + } else { puts("No"); } +} +//ɾϷ +//һnи, ÿοɾһ +//ҶӽڵSGֵΪ0, ҶӽڵSGֵΪкӽڵ(SGֵ + 1) + +================̬滮================== +//Ӷκ O(n) +ll maxSum(int a[], int n, int &st, int &ed) { + ll mx = a[0], mxc = 0; st = ed = 0; + for (int i = 1; i < n; i++) { + if (mxc > 0) { mxc += a[i]; } + else { mxc = a[i]; s = i; } + if (mxc > mx) { mx = mxc; st = s; ed = i; } + } + return mx; +} +//ѭӶκ O(n) +const ll INF = 0x7f7f7f7f7f7fLL; +ll maxSum_adj(int a[], int n) { + ll mx = -INF, mxc = 0, mn = INF, mnc = 0, sum = 0; + for (int i = 0; i < n; i++) { + mxc = a[i] + (mxc > 0 ? mxc : 0); + if (mx < mxc) { mx = mxc; } + mnc = a[i] + (mnc > 0 ? 0 : mnc); + if (mn > mnc) { mn = mnc; } + sum += a[i]; + } + return mx < 0 || mx > sum - mn ? mx : sum - mn; +} +//MӶκ O(nm) +ll dp[N], mxsum[N]; +ll mxMSum(int a[], int n, int m) { + ll mx; + for (int i = 1; i <= m; i++) { + mx = 0x8f8f8f8f8f8f8f8fLL; + for (int j = i; j <= n; j++) { + dp[j] = max(dp[j - 1], mxsum[j - 1]) + a[j]; + mxsum[j - 1] = mx; mx = max(mx, dp[j]); + } + } + return mx; +} +// O(n^3) +ll presum[N][N]; +ll maxSum(int a[][N], int h, int w, int &x1, int &y1, int &x2, int &y2) { + ll ret = a[0][0], sum; x1 = y1 = x2 = y2 = 0; + for (int i = 0; i < h; i++) { + presum[i][0] = 0; + for (int j = 0; j < w; j++) { presum[i][j + 1] = presum[i][j] + a[i][j]; } + } + for (int j = 0; j < w; j++) { + for (int k = j, s; k < w; k++) { + sum = s = 0; + for (int i = 0; i < h; i++, s = sum > 0 ? s : i) { + if ((sum = (sum > 0 ? sum : 0) + presum[i][k + 1] - presum[i][j]) > ret) { + ret = sum; x1 = s; y1 = j; x2 = i; y2 = k; + } + } + } + } + return ret; +} +// Longest Increasing Subsequence O(nlogn) +int b[N]; +int LIS(int a[], int n) { + int len = 1; b[0] = a[0]; + for (int i = 1; i < n; i++) { + b[a[i] > b[len - 1] ? len++ : lower_bound(b, b + len, a[i]) - b] = a[i]; //ǽΪ>=upper_bound + } + return len; +} +// O(nlogn)? +int b[N], l[N]; ll cnt[N]; +vector v[N]; +ll LIS(int a[], int n) { + int len = 1; b[0] = a[0]; l[0] = 1; v[1].push_back(0); + for (int i = 1; i < n; i++) { + int pos = a[i] > b[len - 1] ? len++ : lower_bound(b, b + len, a[i]) - b; + b[pos] = a[i]; l[i] = pos + 1; + v[l[i]].push_back(i); + } + ll ret = 0; + for (int i = 0; i < n; i++) { + if (l[i] == 1) { cnt[i] = 1; continue; } + for (int j = 0, ll = l[i] - 1; j < (int)v[ll].size() && v[ll][j] <= i; j++) { + if (a[v[ll][j]] < a[i]) { cnt[i] += cnt[v[ll][j]]; } + } + if (l[i] == len) { ret += cnt[i]; } + } + return ret; +} +//Ϊkи O(knlogn) +int n, k; +ll bit[M][N]; +inline int lowbit(int x) { return x & -x; } +void add(int id, int i, ll val) { while (i <= n) { bit[id][i] += val; i += lowbit(i); } } +ll sum(int id, int i) { ll ret = 0; while (i) { ret += bit[id][i]; i -= lowbit(i); } return ret; } +int main() { + scanf("%d%d", &n, &k); + add(0, 1, 1); + for (int i = 1, x; i <= n; i++) { + scanf("%d", &x); + for (int j = 1; j <= k; j++) { add(j, x, sum(j - 1, x - 1)); } //ǽΪx + } + printf("%I64d\n", sum(k, n)); //nΪԪֵ +} +// Longest Common Subsequence O(n^2) +int dp[N][N]; +int LCS(char *a, char *b) { + int m = strlen(a), n = strlen(b); + for (int i = 1; i <= m; i++) { + for (int j = 1; j <= n; j++) { + if (a[i - 1] == b[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } + else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } + } + } + return dp[m][n]; +} +void printLCS(char *a, char *b) { + char s[N] = {0}; + for (int i = strlen(a), j = strlen(b), k = dp[i][j]; i && j;) { + if (a[i - 1] == b[j - 1] && dp[i][j] == dp[i - 1][j - 1] + 1) { s[--k] = a[--i]; --j; } + else if (dp[i - 1][j] > dp[i][j - 1]) { i--; } + else { j--; } + } + puts(s); +} +//Ӵ Longest Common Substring +//DP O(n^2) +int dp[2][N]; +int LCS_dp(char *a, char *b, int &st1, int &st2) { + int m = strlen(a), n = strlen(b), ret = 0, cur = 0; st1 = st2 = -1; + for (int i = 0; i < m; i++, cur ^= 1) { + for (int j = 0; j < n; j++) { + if (a[i] == b[j]) { + dp[cur][j] = i == 0 || j == 0 ? 1 : dp[cur ^ 1][j - 1] + 1; + if (dp[cur][j] > ret) { ret = dp[cur][j]; st1 = i + 1 - ret; st2 = j + 1 - ret; } + } + } + } + //outputLCS(a, ret, st1); + return ret; +} +//׺ O(nlogn) +char *suf[N]; +int pstrcmp(const void *p, const void *q) { + return strcmp(*(char **)p, *(char **)q); +} +int comlen_suf(const char *p, const char *q) { + for (int len = 0; *p && *q && *p++ == *q++;) { + len++; + if (*p == '#' || *q == '#') { return len; } + } + return 0; +} +int LCS_suffix(char *a, char *b) { + int m = strlen(a), n = strlen(b), ret = 0, suf_index = 0, len_suf = m + n + 1; + char *arr = new char[len_suf + 1]; + strcpy(arr, a); arr[m] = '#'; strcpy(arr + m + 1, b); + for (int i = 0; i < len_suf; i++) { suf[i] = &arr[i]; } + qsort(suf, len_suf, sizeof(char *), pstrcmp); + for (int i = 0; i < len_suf - 1; i++) { + int len = comlen_suf(suf[i], suf[i + 1]); + if (len > ret) { ret = len; suf_index = i; } + } + //outputLCS(suf[suf_index], ret); + delete[] arr; return ret; +} +void outputLCS(char *s, int len, int i = 0) { + for (; len--; i++) { putchar(s[i]); } puts(""); +} +//DP ½O(nlogn) ϽO(nmlog(nm)) +int c[N * N], d[N * N]; +int LCS_dp(char *a, char *b) { + vector pos[26]; int k = 0, len = 1; d[0] = c[0]; + for (int i = strlen(b) - 1; i >= 0; i--) { pos[b[i] - 'a'].push_back(i); } + for (int i = 0; a[i]; i++) { + for (int j = 0; j < (int)pos[a[i] - 'a'].size(); j++) { c[k++] = pos[a[i] - 'a'][j]; } + } + for (int i = 1; i < k; i++) { + d[c[i] > d[len - 1] ? len++ : lower_bound(d, d + len, c[i]) - d] = c[i]; + } + return len; +} +// GCIS O(n^2) +int dp[N], f[N][N]; +int GCIS(int a[], int la, int b[], int lb, int ans[]) { + //a[1...la], b[1...lb] + int mx = 0; + memset(f, 0, sizeof(f)); + memset(dp, 0, sizeof(dp)); + for (int i = 1; i <= la; i++) { + memcpy(f[i], f[i - 1], sizeof(f[0])); + for (int j = 1, k = 0; j <= lb; j++) { + if (a[j - 1] > b[i - 1] && dp[k] < dp[j]) { k = j; } + if (b[j - 1] == a[i - 1] && dp[k] + 1 > dp[j]) { dp[j] = dp[k] + 1; f[i][j] = i * (lb + 1) + k; } + } + } + for (int i = 1; i <= lb; i++) { if (dp[i] > dp[mx]) { mx = i; } } + for (int i = la * lb + la + mx, j = dp[mx]; j; i = f[i / (lb + 1)][i % (lb + 1)], j--) { + ans[j - 1] = b[i % (lb + 1) - 1]; + } + return dp[mx]; +} +//ַ༭ (Levenshtein) +//滻һַ, һַ, ɾһַ +int dp[N][N]; +int LevDist(char *a, char *b) { + int n = strlen(a), m = strlen(b); + for (int i = 0; i <= n; i++) { dp[i][0] = i; } + for (int i = 0; i <= m; i++) { dp[0][i] = i; } + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1; + if (a[i - 1] == b[j - 1]) { dp[i][j] = min(dp[i][j], dp[i - 1][j - 1]); } + else { dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + 1); } + } + } + return dp[n][m]; +} +//ַ +//ǿոַľ붨ΪǵASCIIIJľֵ, ոַַ֮ľΪ֪Ķֵk +int dp[N][N]; +int dist(char *a, char *b, int k) { + int n = strlen(a), m = strlen(b); + for (int i = 0; i <= n; i++) { dp[i][0] = i * k; } + for (int i = 1; i <= m; i++) { dp[0][i] = i * k; } + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + dp[i][j] = min(dp[i - 1][j - 1] + abs(a[i - 1] - b[j - 1]), min(dp[i - 1][j], dp[i][j - 1]) + k); + } + } + return dp[n][m]; +} +//TSP O(V^2*2^V) +int n, mp[N][N], dp[1 << N][N]; +int TSP() { + memset(dp, 0x1f, sizeof(dp)); + dp[1][0] = 0; + for (int s = 0; s < 1 << n; s++) { + for (int v = 0; v < n; v++) { + if (dp[s][v] == 0x1f1f1f1f) { continue; } + for (int u = 0; u < n; u++) { + if (s & 1 << u) { continue; } + dp[s | 1 << u][u] = min(dp[s | 1 << u][u], dp[s][v] + mp[v][u]); + } + } + } + int ans = 0x1f1f1f1f; + for (int i = 0; i < n; i++) { ans = min(ans, dp[(1 << n) - 1][i] + mp[i][0]); } + return ans; +} +//mTSP O(V^2*2^V) +int n, mp[N][N], dp[1 << N][N], best[1 << N]; +bool ok[1 << N]; //ü״̬Ƿ +int mTSP() { + memset(dp, 0x1f, sizeof(dp)); + memset(best, 0x1f, sizeof(best)); + dp[1][0] = 0; + for (int s = 0; s < 1 << n; s++) { + if (!ok[s]) { continue; } + for (int v = 0; v < n; v++) { + if (!(s & (1 << v)) || dp[s][v] == 0x1f1f1f1f) { continue; } + best[s] = min(best[s], dp[s][v] + mp[v][0]); + for (int u = 0; u < n; u++) { + if (s & (1 << u)) { continue; } + dp[s | 1 << u][u] = min(dp[s | 1 << u][u], dp[s][v] + mp[v][u]); + } + } + } + for (int s = 0; s < 1 << n; s++) { + if (!(s & 1)) { continue; } + for (int i = s & (s - 1); i; i = s & (i - 1)) { + best[s] = min(best[s], best[i] + best[(s ^ i) | 1]); + } + } + return best[(1 << n) - 1]; +} + +==========================ڿƼ======================== +//ջ +//G++ +int main() { + int sz = 100 << 20; //100MB + char *p = (char *)malloc(sz) + sz; + __asm__ __volatile__( +#if __x86_64__ || __ppc64__ || _WIN64 //64-bit + "movq %0, %%rsp\n pushq $_exit\n" +#else //32-bit + "movl %0, %%esp\n pushl $_exit\n" +#endif + :: "r"(p)); + //...... + exit(0); +} +//VC++ 100MB +#pragma comment(linker, "/STACK:102400000,102400000") + +//λ +//ұ10 | (100101111->100100000) | x and (x+1) +//һ01 | (100101111->100111111) | x or (x+1) +//ұ01 | (11011000->11011111) | x or (x-1) +//ȡұ1 | (100101111->1111) | (x xor (x+1)) shr 1 +//ȥһ1 | (100101000->1000) | x and (x xor (x-1)) +//öiķǿӼj +for (int j = i; j; j = (j - 1) & i); + +//builtin +int __builtin_ffs(int x); +int __builtin_ffsll(long long); +//Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +int __builtin_clz(unsigned int x); +int __builtin_clzll(unsigned long long); +//Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +int __builtin_ctz(unsigned int x); +int __builtin_ctzll(unsigned long long); +//Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +int __builtin_clrsb(int x); +int __builtin_clrsbll(long long); +//Returns the number of leading redundant sign bits in x, i.e. the number of bits following the most significant bit that are identical to it. There are no special cases for 0 or other values. +int __builtin_popcount(unsigned int x); +int __builtin_popcountll(unsigned long long); +//Returns the number of 1-bits in x. +int __builtin_parity(unsigned int x); +int __builtin_parityll(unsigned long long); +//Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +uint32_t __builtin_bswap32(uint32_t x); +uint64_t __builtin_bswap64(uint64_t x); +//Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. + +//rope O(log(len)) +#include +using namespace __gnu_cxx; + +//pb_ds +//http://gaotianyu1350.gitcafe.io/2015/02/17/pbds/ +//priority_queue +// +//ext/pb_ds/priority_queue.hpp +//__gnu_pbds::priority_queue +//ģ +//template, +// typename Tag = pairing_heap_tag, +// typename Allocator = std::allocator> +//class priority_queue; +//Value_Type +//Cmp_FnԶȽ +//Tagѵ͡binary_heap_tagѣbinomial_heap_tagѣrc_binomial_heap_tag pairing_heap_tagԶѣthin_heap_tag +//Allocatorù +//ʹ +//STLеpriority_queue +//begin()end()ȡӶ +//ɾԪvoid erase(point_iterator) +//ӻijһԪصֵvoid modify(point_iterator, const_reference) +//ϲvoid join(priority_queue &other)otherϲ*thisother +//ܷ +//ֲpushpopmodifyerasejoin +//pairing_heap_tagpushjoinO(1)̯O(logn) +//binary_heap_tagֻ֧pushpopΪ̯O(logn) +//binomial_heap_tagpushΪ̯O(1)ΪO(logn) +//rc_binomial_heap_tagpushΪO(1)ΪO(logn) +//thin_heap_tagpushΪO(1)֧joinΪO(logn)ֻincrease_keymodify̯O(1) +//ֲ֧Dzã +//½ۣ +//ŻDijkstra㷨pairing_heap_tagϸthin_heap_tagٶдݽṹ൱ +//߶󷨺 +//binary_heap_tagھstd::priority_queue +//pairing_heap_tagھbinomial_heap_tagrc_binomial_heap_tag +//ֻpushpopjoinʱbinary_heap_tagٶȽϿ +//modifyʱԿpairing_heap_tagthin_heap_tagдݽṹ + +//Tree +// +//ext/pb_ds/assoc_container.hppext/pb_ds/tree_policy.hpp +//__gnu_pbds::tree +//ģ +//template, +// typename Tag = rb_tree_tag, +// template +// class Node_Update = null_tree_node_update, +// typename Allocator = std::allocator> +//class tree; +//Tagtreeͣrb_tree_tagsplay_tree_tagov_tree_tag +//Node_UpdateΪգҲpb_dsԴtree_order_statistics_node_updatetreeͻfind_by_orderorder_of_key +//iterator find_by_order(size_type order)ҵorder + 1СԪصĵorder̫᷵end() +//size_type order_of_key(const_key_reference r_key)ѯtreeжٱr_keyСԪ +//ʹ +//mapʹ÷ͬbegin()end()size()empty()clear()find(const Key) +//lower_bound(const Key)upper_bound(const Key)erase(iterator)erase(const Key) +//insert(const pair)operator[](const Key) +//ijsetֻҪڶMappedΪnull_type4.4.0°汾ıӦnull_mapped_typeͿˡʱָͻpairKeysetû +//ȻһЩ÷磺 +//void join(tree &other)otherԪƶ*thisϣֵཻ׳쳣 +//void split(const_key_reference r_key, tree &other)otherȻ*thisдr_keyԪƶother +//ԶNode_Updateʹ÷ +//Դtree_order_statistics_node_updateͳƵsize +//Լ޸ľͿͳ׺ϲϢ +//´ʵ +template +struct my_node_update { + virtual Node_CItr node_begin()const = 0; + virtual Node_CItr node_end()const = 0; + typedef int metadata_type; //ڵϼ¼ĶϢ + inline void operator()(Node_Itr it, Node_CItr end_it) { + Node_Itr l = it.get_l_child(), r = it.get_r_child(); + int left = 0, right = 0; + if (l != end_it) { left = l.get_metadata(); } + if (r != end_it) { right = r.get_metadata(); } + const_cast(it.get_metadata()) = left + right + (*it)->second; + } + inline int prefix_sum(int x) { + int ans = 0; + Node_CItr it = node_begin(); + while (it != node_end()) { + Node_CItr l = it.get_l_child(), r = it.get_r_child(); + if (Cmp_Fn()(x, (*it)->first)) { it = l; } + else { + ans += (*it)->second; + if (l != node_end()) { ans += l.get_metadata(); } + it = r; + } + } + return ans; + } + inline int interval_sum(int l, int r) { + return prefix_sum(r) - prefix_sum(l - 1); + } +}; +int main() { + tree, rb_tree_tag, my_node_update> T; + T[2] = 100; T[3] = 1000; T[4] = 10000; + printf("%d\n%d\n", T.interval_sum(3, 4), T.prefix_sum(3)); +} +//ע⣺ +//Node_Itr飺get_l_childget_r_childȡҶӣǺţһǺֻǻȡiteratorȡڵϢget_metadataȡڵϢ +//operator()ĹǽڵitϢ£end_itʾսڵ +//ܷ +//дݽṹ࣬rb_tree_tagҪ + +//Hash +// +//ext/pb_ds/assoc_container.hppext/pb_ds/hash_policy.hpp +// +//__gnu_pbds::cc_hash_table +//__gnu_pbds::gp_hash_table +//ʹ +//֧findoperator[] + +//Trie +// +//ext/pb_ds/assoc_container.hppext/pb_ds/trie_policy.hpp +//__gnu_pbds::trie +//ģ +//template, +// typename Tag = pat_trie_tag, +// template +// class Node_Update = null_trie_node_update, +// typename Allocator = std::allocator> +//class trie; +//Key is the key type. +//Mapped is the mapped-policy, and is explained in Tutorial::Associative Containers::Associative Containers Others than Maps. +//E_Access_Traits is described in Element-Access Traits. +//Tag specifies which underlying data structure to use, and is described shortly. +//Node_Update is a policy for updating node invariants. This is described in Node Invariants. +//Allocator is an allocator type. +//ܣ +//pair prefix_range(key_const_reference) +//Finds the const iterator range corresponding to all values whose prefixes match r_key +//trieģôдtrie, pat_trie_tag, trie_prefix_search_node_update> + +//Listmultimap/multiset +// +//ext/pb_ds/assoc_container.hppext/pb_ds/list_update_policy.hpp +//__gnu_pbds::list_update +//ģ +//template, +// typename Update_Policy = move_to_front_lu_policy<>, +// typename Allocator = std::allocator> +//class list_update; + +//ܽ +//priority_queueSTL֧modifyerasejoin +//tree൱STLеset/map֧splitjointree_order_statistics_node_updateֲ֧ѯrankkСֵԶNode_UpdateάϢ +//ĿǰУSTLûеhash_table +//pb_dsstd::set/map/priority_queueʹø + + +=================================== +// +template struct mat { + vector a; int h, w; + mat(): a(), h(), w() {} + mat(const mat &v): a(v.a), h(v.h), w(v.w) {} + mat(const int &_h, const int &_w): a(_h * _w), h(_h), w(_w) { } + void init() { a.clear(); a.resize(h * w); } + static mat e(const int &_h, const int &_w) { + mat res(_h, _w); + for (int i = 0, n = min(_h, _w); i < n; i++) { res[i][i] = 1; } + return res; + } + static mat e(const mat &b) { return e(b.h, b.w); } + T *operator[](const int &v) { return &a[v * w]; } + const T *operator[](const int &v)const { return &a[v * w]; } + mat &operator+=(const mat &b) { + for (int i = 0, n = h * w; i < n; i++) { a[i] += b.a[i]; } + return *this; + } + mat &operator-=(const mat &b) { return *this += -b; } + mat &operator*=(const mat &b) { + mat c(h, b.w); + for (int i = 0; i < h; i++) { + for (int k = 0; k < w; k++) { + const T &tmp = (*this)[i][k]; + if (isZero(tmp)) { continue; } + for (int j = 0; j < b.w; j++) { c[i][j] = (c[i][j] + tmp * b[k][j])/*%M*/; } + } + } + swap(a, c.a); h = c.h; w = c.w; return *this; + } + mat operator-()const { + mat ret(*this); + for (int i = 0, n = h * w; i < n; i++) { ret.a[i] = -ret.a[i]; } + return ret; + } + mat operator+(const mat &b)const { return mat(*this) += b; } + mat operator-(const mat &b)const { return mat(*this) -= b; } + mat operator*(const mat &b)const { return mat(*this) *= b; } + mat operator^(const ll &v)const { + mat ret(e(*this)), t(*this); + for (ll b = v; b; b >>= 1) { if (b & 1) { ret *= t; } t *= t; } + return ret; + } + bool operator==(const mat &b)const { + if (h != b.h || w != b.w) { return false; } + for (int i = 0, n = h * w; i < n; i++) { if (!isZero(a[i] - b.a[i])) { return false; } } + return true; + } + bool operator!=(const mat &b)const { return !(*this == b); } + T abs(const T &v)const { return v < 0 ? -v : v; } + bool isZero(const T &v)const { return abs(v) < 1e-9; } + void input() { for (int i = 0, n = h * w; i < n; i++) { scanf("%I64d", &a[i]); } } + void print()const { + for (int i = 0, n = h * w; i < n; i++) { printf("%I64d%c", a[i], i % w == w - 1 ? '\n' : ' '); } + } + mat trans()const { + mat ret(w, h); + for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { ret[i][j] = a[j][i]; } } + return ret; + } + // double 򷵻true ڲv + bool inv(mat &v)const { + if (h != w) { return false; } + int is[N], js[N]; v = *this; + for (int k = 0; k < h; k++) { + double t = 0; + for (int i = k; i < h; i++) { + for (int j = k; j < h; j++) { + if (abs(v[i][j]) > t) { t = abs(v[is[k] = i][js[k] = j]); } + } + } + if (isZero(t)) { return false; } + if (is[k] != k) { for (int j = 0; j < h; j++) { swap(v[k][j], v[is[k]][j]); } } + if (js[k] != k) { for (int i = 0; i < h; i++) { swap(v[i][k], v[i][js[k]]); } } + v[k][k] = 1.0 / v[k][k]; + for (int j = 0; j < h; j++) { if (j != k) { v[k][j] *= v[k][k]; } } + for (int i = 0; i < h; i++) { + if (i != k) { for (int j = 0; j < h; j++) { if (j != k) { v[i][j] -= v[i][k] * v[k][j]; } } } + } + for (int i = 0; i < h; i++) { if (i != k) { v[i][k] *= -v[k][k]; } } + } + for (int k = h - 1; k >= 0; k--) { + for (int j = 0; j < h; j++) { if (js[k] != k) { swap(v[k][j], v[js[k]][j]); } } + for (int i = 0; i < h; i++) { if (is[k] != k) { swap(v[i][k], v[i][is[k]]); } } + } + return true; + } + //ʽģM Ԫ + ll detmod()const { + if (h != w) { return 0; } + ll res = 1; mat c(*this); + for (int i = 0; i < h; i++) { + for (int j = 0; j < h; j++) { c[i][j] = (c[i][j] % M + M) % M; } + } + for (int i = 0; i < h; i++) { + for (int j = i; j < h; j++) { + if (c[j][i] != 0) { + for (int k = i; k < h; k++) { swap(c[i][k], c[j][k]); } + if (i != j) { res = (-res + M) % M; } + break; + } + } + if (c[i][i] == 0) { res = -1; break; } + for (int j = i + 1; j < h; j++) { + //int mul = (c[j][i] * Inv[c[i][i]]) % M; //Ԫ + ll mul = (c[j][i] * inv(c[i][i], M)) % M; + for (int k = i; k < h; k++) { c[j][k] = (c[j][k] - (c[i][k] * mul) % M + M) % M; } + } + res = (res * c[i][i]) % M; + } + return res; + } + //ʽ double + double det()const { + if (h != w) { return 0; } + int sign = 0; double ret = 1.0; mat c(*this); + for (int i = 0, j, k; i < h; i++) { + if (isZero(c[i][i])) { + for (j = i + 1; j < h && isZero(c[j][i]); j++); + if (j == h) { return 0; } + for (k = i; k < h; k++) { swap(c[i][k], c[j][k]); } + sign++; + } + ret *= c[i][i]; + for (k = i + 1; k < h; k++) { c[i][k] /= c[i][i]; } + for (j = i + 1; j < h; j++) { for (k = i + 1; k < h; k++) { c[j][k] -= c[j][i] * c[i][k]; } } + } + return sign & 1 ? -ret : ret; + } +}; + + + diff --git a/.ACM-Templates/TXTs/矩阵.txt b/.ACM-Templates/TXTs/矩阵.txt new file mode 100644 index 0000000..070fa1e --- /dev/null +++ b/.ACM-Templates/TXTs/矩阵.txt @@ -0,0 +1,131 @@ +// +template struct mat { + vector a; int h, w; + mat(): a(), h(), w() {} + mat(const mat &v): a(v.a), h(v.h), w(v.w) {} + mat(const int &_h, const int &_w): a(_h * _w), h(_h), w(_w) { } + void init() { a.clear(); a.resize(h * w); } + static mat e(const int &_h, const int &_w) { + mat res(_h, _w); + for (int i = 0, n = min(_h, _w); i < n; i++) { res[i][i] = 1; } + return res; + } + static mat e(const mat &b) { return e(b.h, b.w); } + T *operator[](const int &v) { return &a[v * w]; } + const T *operator[](const int &v)const { return &a[v * w]; } + mat &operator+=(const mat &b) { + for (int i = 0, n = h * w; i < n; i++) { a[i] += b.a[i]; } + return *this; + } + mat &operator-=(const mat &b) { return *this += -b; } + mat &operator*=(const mat &b) { + mat c(h, b.w); + for (int i = 0; i < h; i++) { + for (int k = 0; k < w; k++) { + const T &tmp = (*this)[i][k]; + if (isZero(tmp)) { continue; } + for (int j = 0; j < b.w; j++) { c[i][j] = (c[i][j] + tmp * b[k][j])/*%M*/; } + } + } + swap(a, c.a); h = c.h; w = c.w; return *this; + } + mat operator-()const { + mat ret(*this); + for (int i = 0, n = h * w; i < n; i++) { ret.a[i] = -ret.a[i]; } + return ret; + } + mat operator+(const mat &b)const { return mat(*this) += b; } + mat operator-(const mat &b)const { return mat(*this) -= b; } + mat operator*(const mat &b)const { return mat(*this) *= b; } + mat operator^(const ll &v)const { + mat ret(e(*this)), t(*this); + for (ll b = v; b; b >>= 1) { if (b & 1) { ret *= t; } t *= t; } + return ret; + } + bool operator==(const mat &b)const { + if (h != b.h || w != b.w) { return false; } + for (int i = 0, n = h * w; i < n; i++) { if (!isZero(a[i] - b.a[i])) { return false; } } + return true; + } + bool operator!=(const mat &b)const { return !(*this == b); } + T abs(const T &v)const { return v < 0 ? -v : v; } + bool isZero(const T &v)const { return abs(v) < 1e-9; } + void input() { for (int i = 0, n = h * w; i < n; i++) { scanf("%I64d", &a[i]); } } + void print()const { + for (int i = 0, n = h * w; i < n; i++) { printf("%I64d%c", a[i], i % w == w - 1 ? '\n' : ' '); } + } + mat trans()const { + mat ret(w, h); + for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { ret[i][j] = a[j][i]; } } + return ret; + } + // double 򷵻true ڲv + bool inv(mat &v)const { + if (h != w) { return false; } + int is[N], js[N]; v = *this; + for (int k = 0; k < h; k++) { + double t = 0; + for (int i = k; i < h; i++) { + for (int j = k; j < h; j++) { + if (abs(v[i][j]) > t) { t = abs(v[is[k] = i][js[k] = j]); } + } + } + if (isZero(t)) { return false; } + if (is[k] != k) { for (int j = 0; j < h; j++) { swap(v[k][j], v[is[k]][j]); } } + if (js[k] != k) { for (int i = 0; i < h; i++) { swap(v[i][k], v[i][js[k]]); } } + v[k][k] = 1.0 / v[k][k]; + for (int j = 0; j < h; j++) { if (j != k) { v[k][j] *= v[k][k]; } } + for (int i = 0; i < h; i++) { + if (i != k) { for (int j = 0; j < h; j++) { if (j != k) { v[i][j] -= v[i][k] * v[k][j]; } } } + } + for (int i = 0; i < h; i++) { if (i != k) { v[i][k] *= -v[k][k]; } } + } + for (int k = h - 1; k >= 0; k--) { + for (int j = 0; j < h; j++) { if (js[k] != k) { swap(v[k][j], v[js[k]][j]); } } + for (int i = 0; i < h; i++) { if (is[k] != k) { swap(v[i][k], v[i][is[k]]); } } + } + return true; + } + //ʽģM Ԫ + ll detmod()const { + if (h != w) { return 0; } + ll res = 1; mat c(*this); + for (int i = 0; i < h; i++) { + for (int j = 0; j < h; j++) { c[i][j] = (c[i][j] % M + M) % M; } + } + for (int i = 0; i < h; i++) { + for (int j = i; j < h; j++) { + if (c[j][i] != 0) { + for (int k = i; k < h; k++) { swap(c[i][k], c[j][k]); } + if (i != j) { res = (-res + M) % M; } + break; + } + } + if (c[i][i] == 0) { res = -1; break; } + for (int j = i + 1; j < h; j++) { + //int mul = (c[j][i] * Inv[c[i][i]]) % M; //Ԫ + ll mul = (c[j][i] * inv(c[i][i], M)) % M; + for (int k = i; k < h; k++) { c[j][k] = (c[j][k] - (c[i][k] * mul) % M + M) % M; } + } + res = (res * c[i][i]) % M; + } + return res; + } + //ʽ double + double det()const { + if (h != w) { return 0; } + int sign = 0; double ret = 1.0; mat c(*this); + for (int i = 0, j, k; i < h; i++) { + if (isZero(c[i][i])) { + for (j = i + 1; j < h && isZero(c[j][i]); j++); + if (j == h) { return 0; } + for (k = i; k < h; k++) { swap(c[i][k], c[j][k]); } + sign++; + } + ret *= c[i][i]; + for (k = i + 1; k < h; k++) { c[i][k] /= c[i][i]; } + for (j = i + 1; j < h; j++) { for (k = i + 1; k < h; k++) { c[j][k] -= c[j][i] * c[i][k]; } } + } + return sign & 1 ? -ret : ret; + } +}; diff --git a/.ACM-Templates/TXTs/稀疏表.txt b/.ACM-Templates/TXTs/稀疏表.txt new file mode 100644 index 0000000..3f5273d --- /dev/null +++ b/.ACM-Templates/TXTs/稀疏表.txt @@ -0,0 +1,41 @@ +//ϡ Sparse Table +//һάRMQ ԤO(nlogn) ѯO(1) +//ֵ ±1ʼ ޸ļɷ± +int p[N] = { -1}, dp[N][20]; +void initRMQ() { + for (int i = 1; i <= n; i++) { p[i] = p[i >> 1] + 1; dp[i][0] = a[i]; } + for (int j = 1; j <= p[n]; j++) { + for (int i = 1; i + (1 << j) - 1 <= n; i++) { + dp[i][j] = dp[i][j - 1] > dp[i + (1 << (j - 1))][j - 1] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1]; + } + } +} +inline int query(int l, int r) { + if (l > r) { swap(l, r); } + int k = p[r - l + 1]; + return dp[l][k] > dp[r - (1 << k) + 1][k] ? dp[l][k] : dp[r - (1 << k) + 1][k]; +} +//άRMQ ԤO(nmlognlogm) ѯO(1) ±1ʼ +int p[N] = { -1}, dp[N][N][9][9]; +void initRMQ() { + for (int i = 1; i <= n; i++) { + p[i] = p[i >> 1] + 1; + for (int j = 1; j <= n; j++) { dp[i][j][0][0] = a[i][j]; } + } + for (int ii = 0; ii <= p[n]; ii++) { + for (int jj = 0; jj <= p[m]; jj++) { + if (ii + jj == 0) { continue; } + for (int i = 1; i + (1 << ii) - 1 <= n; i++) { + for (int j = 1; j + (1 << jj) - 1 <= m; j++) { + if (ii) { dp[i][j][ii][jj] = max(dp[i][j][ii - 1][jj], dp[i + (1 << (ii - 1))][j][ii - 1][jj]); } + else { dp[i][j][ii][jj] = max(dp[i][j][ii][jj - 1], dp[i][j + (1 << (jj - 1))][ii][jj - 1]); } + } + } + } + } +} +inline int query(int x1, int y1, int x2, int y2) { + if (x1 > x2) { swap(x1, x2); } if (y1 > y2) { swap(y1, y2); } + int k1 = p[x2 - x1 + 1], k2 = p[y2 - y1 + 1]; x2 -= (1 << k1) - 1; y2 -= (1 << k2) - 1; + return max(max(dp[x1][y1][k1][k2], dp[x1][y2][k1][k2]), max(dp[x2][y1][k1][k2], dp[x2][y2][k1][k2])); +} diff --git a/.ACM-Templates/TXTs/组合数学.txt b/.ACM-Templates/TXTs/组合数学.txt new file mode 100644 index 0000000..03439ff --- /dev/null +++ b/.ACM-Templates/TXTs/组合数学.txt @@ -0,0 +1,183 @@ +//Ԥ / O(n^2) +//C[i][i] = C[i][0] = 1 +//C[i][j] = C[i - 1][j] + C[i - 1][j - 1], 0 < j < i +const int maxc = 105; +ll C[maxc][maxc]; +void calC() { + for (int i = 0; i < maxc; i++) { C[i][i] = C[i][0] = 1; } + for (int i = 2; i < maxc; i++) { + for (int j = 1; j < i; j++) { C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % M; } + } +} +//ȡģ O(n) +ll Com(ll n, ll m) { + if (m > n) { return 0; } + if (m > n - m) { m = n - m; } + ll ret = 1; + for (ll i = 0, j = 1; i < m; i++) { + for (ret *= n - i; j <= m && ret % j == 0; j++) { ret /= j; } + } + return ret; +} +//ȡģ +//p <= 1e6 Ԥ׳Ԫ O(min(n, p)) + O(1) +ll fac[M] = {1, 1}, invfac[M] = {1, 1}; +void initFac(ll p) { + for (int i = 2; i < p; i++) { + fac[i] = fac[i - 1] * i % p; invfac[i] = (-invfac[p % i] * (p / i) % p + p) % p; + } + for (int i = 2; i < p; i++) { invfac[i] = invfac[i] * invfac[i - 1] % p; } +} +ll Com(ll n, ll m, ll p) { + return n < m ? 0 : fac[n] * invfac[n - m] % p * invfac[m] % p; +} +//p <= 1e9 Ԫ O(nlogp) +ll Com(ll n, ll m, ll p) { + if (m > n) { return 0; } + if (m > n - m) { m = n - m; } + ll ret = 1; + for (ll i = 1; i <= m; i++) { + ll a = (n + i - m) % p, b = i % p; + ret = ret * a % p * powMod(b, p - 2, p) % p; + } + return ret; +} +//Lucas +ll Lucas(ll n, ll m, ll p) { + if (n < m) { return 0; } + if (m == 0 && n == 0) { return 1; } + return Com(n % p, m % p, p) * Lucas(n / p, m / p, p) % p; +} +//һStirling s(p, k) +//pųkǿѭеķ +//s(p, k)ĵƹʽs(p, k) = (p - 1) * s(p - 1, k) + s(p - 1, k - 1), 1 <= k <= p - 1 +//߽s(p, 0) = 0, p >= 1, s(p, p) = 1, p >= 0 +const int maxs = 105; +ll S[maxs][maxs]; +void calStir1() { + S[0][0] = S[1][1] = 1; + for (int i = 2; i < maxs; i++) { + for (int j = 1; j <= i; j++) { S[i][j] = ((i - 1) * S[i - 1][j] + S[i - 1][j - 1]) % M; } + } +} +//ڶStirling S(p, k) +//p廮ֳkǿյIJɱ(Ϊûб)ϵķ +//k! * S(p, k)ǰp˷ֽkв(类з)ķ(޿շ)ķ +//S(p, k)ĵƹʽǣS(p, k) = k * S(p - 1, k) + S(p - 1, k - 1), 1 <= k <= p - 1 +//߽S(p, 0) = 0, p >= 1, S(p, p) = 1, p >= 0 +const int maxs = 105; +ll S[maxs][maxs]; +void calStir2() { + S[0][0] = S[1][1] = 1; + for (int i = 2; i < maxs; i++) { + for (int j = 1; j <= i; j++) { S[i][j] = (j * S[i - 1][j] + S[i - 1][j - 1]) % M; } + } +} +//Bell +//B(n)ʾΪnļϵĻַĿ +//B(0) = 1, B(n + 1) = sum(C(n, k) * B(k)), 0 <= k <= n +//ÿǵڶStirlingĺ, B(n) = sum(S(n, k)), 1 <= k <= n +//Bell +//a[0][0] = 1 +//n >= 1, a[n][0] = a[n - 1][n - 1] +//m, n >= 1, a[n][m] = a[n][m - 1] + a[n - 1][m - 1] +//ÿDZÿ֮ǵڶStirling +//Ҫͬ: +//B(p + n) = B(n) + B(n + 1) (mod p) +//B(p^m + n) = m * B(n) + B(n + 1) (mod p) +//pDz100, , ǿͨBellģС100ֵ +//BellģpΪ: N(p) = ((p^p) - 1) / (p - 1) +const int maxb = 105; +ll T[maxb], B[maxb]; +void calBell() { + B[0] = B[1] = T[0] = 1; + for (int i = 2; i < maxb; i++) { + T[i - 1] = B[i - 1]; + for (int j = i - 2; j >= 0; j--) { T[j] = (T[j] + T[j + 1]) % M; } + B[i] = T[0]; + } +} +//Bell(n)999999598 = 2 13 5281 7283ȡģ O(P^2logP) +const int N = 7284, P = 999999598; +ll n; int p[5] = {2, 13, 5281, 7283}, B[2][N], T[N]; +void init() { + T[0] = T[1] = B[0][0] = 1; B[0][1] = 2; + for (int i = 2, crt = 1; i < N; i++, crt ^= 1) { + T[i] = B[crt][0] = B[crt ^ 1][i - 1]; + for (int j = 1; j <= i; j++) { B[crt][j] = (B[crt ^ 1][j - 1] + B[crt][j - 1]) % P; } + } +} +int b[N], c[N], d[70]; +int cal(ll n, int mod) { + int len = 0; + for (int i = 0; i <= mod; i++) { b[i] = T[i] % mod; } + while (n) { d[len++] = n % mod; n /= mod; } + for (int i = 1; i < len; i++) { + for (int j = 1; j <= d[i]; j++) { + for (int k = 0; k < mod; k++) { c[k] = (b[k] * i + b[k + 1]) % mod; } + c[mod] = (c[0] + c[1]) % mod; + for (int k = 0; k <= mod; k++) { b[k] = c[k]; } + } + } + return c[d[0]]; +} +ll bell(ll n) { + if (n < N) { return T[n]; } + ll t = 0; + for (int i = 0; p[i]; i++) { + t = (t + (P / p[i]) * powMod(P / p[i], p[i] - 2, p[i]) % P * cal(n, p[i]) % P) % P; + } + return t; +} +// Catalan Number +//Cat(1) = 1, Cat(n) = (4n - 2) * Cat(n - 1) / (n + 1) = C(2n, n) / (n + 1) = C(2n, n) - C(2n, n - 1) +//(0, 0)ߵ(n, m) +//Խߵķ(x > y): C(n + m - 1, m) - C(n + m - 1, m - 1) +//Խߵķ(x >= y): C(n + m, m) - C(n + m, m - 1) +//Ԥ +int a[105][105], b[105]; //, +void Catalan() { + int i, j, len, carry, temp; + a[1][0] = b[1] = len = 1; + for (i = 2; i <= 100; i++) { + for (j = 0; j < len; j++) { //˷ + a[i][j] = a[i - 1][j] * (4 * (i - 1) + 2); + } + carry = 0; + for (j = 0; j < len; j++) { //˽ + temp = a[i][j] + carry; + a[i][j] = temp % 10; + carry = temp / 10; + } + while (carry) { //λ + a[i][len++] = carry % 10; + carry /= 10; + } + carry = 0; + for (j = len - 1; j >= 0; j--) { // + temp = carry * 10 + a[i][j]; + a[i][j] = temp / (i + 1); + carry = temp % (i + 1); + } + while (!a[i][len - 1]) { len--; } //λ㴦 + b[i] = len; + } +} +// +void printCatalan(int n) { + for (int i = b[n] - 1; i >= 0; i--) { printf("%d", a[n][i]); } +} +//Сźӵķ +//k m Ƿпպ +//ͬ ͬ m^k +//ͬ ͬ m!*Stirling2(k, m) +//ͬ ͬ (m, i=1)Stirling2(k, i) +//ͬ ͬ Stirling2(k, m) +//ͬ ͬ C(m + k - 1, k) +//ͬ ͬ C(k - 1, m - 1) +//ͬ ͬ 1/(1-x)(1-x^2)...(1-x^m)x^kϵ +//ͬ ͬ x^m/(1-x)(1-x^2)...(1-x^m)x^kϵ +//Źʽ +//D(1) = 0, D(2) = 1, D(n) = (n - 1)(D(n - 2) + D(n - 1)) +//չ Cayley ʽ +//n, mͨͼ, ÿͨa[i], ôs - 1߰ͨķΪn^(s-2)a[1]a[2]...a[m] diff --git a/.ACM-Templates/TXTs/莫队.txt b/.ACM-Templates/TXTs/莫队.txt new file mode 100644 index 0000000..299febe --- /dev/null +++ b/.ACM-Templates/TXTs/莫队.txt @@ -0,0 +1,28 @@ +//Ī㷨 O(n^1.5) +//Ī㷨ߴһ䲻޸IJѯ㷨 +//֪[L,R]Ĵ, O(1)ʱµõ[L,R-1][L,R+1][L-1,R][L+1,R]Ĵ𰸵Ļ, ͿʹĪ㷨 +//lydsy 2038: [2009Ҽѵ]СZ(hose) +int n, m; +int c[N], pos[N]; +int ansup[N], ansdn[N], cnt[N]; +struct Node { + int l, r, id; + bool operator<(const Node &b)const { return pos[l] < pos[b.l] || (pos[l] == pos[b.l] && r < b.r); } +} q[N]; +int main() { + while (~scanf("%d%d", &n, &m)) { + memset(cnt, 0, sizeof(cnt)); ll ans = 0; + for (int i = 1, nn = ceil(sqrt(n)); i <= n; i++) { scanf("%d", &c[i]); pos[i] = (i - 1) / nn; } + for (int i = 0; i < m; i++) { scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i; } + sort(q, q + m); + for (int i = 0, l = 1, r = 0; i < m; i++) { + for (; l > q[i].l;) { ans += cnt[c[--l]]++; } + for (; l < q[i].l;) { ans -= --cnt[c[l++]]; } + for (; r < q[i].r;) { ans += cnt[c[++r]]++; } + for (; r > q[i].r;) { ans -= --cnt[c[r--]]; } + ll dn = (r - l + 1LL) * (r - l) >> 1, gcd = __gcd(ans, dn); + ansup[q[i].id] = ans / gcd; ansdn[q[i].id] = dn / gcd; + } + for (int i = 0; i < m; i++) { printf("%d/%d\n", ansup[i], ansdn[i]); } + } +} diff --git a/.ACM-Templates/TXTs/计算几何.txt b/.ACM-Templates/TXTs/计算几何.txt new file mode 100644 index 0000000..6505ad3 --- /dev/null +++ b/.ACM-Templates/TXTs/计算几何.txt @@ -0,0 +1,1393 @@ +//СԲ +//ԲΪO, 뾶ΪR +double R, EPS = 1e-9; +struct Point { double x, y; } a[N], O; +inline double dis(Point x, Point y) { return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y)); } +Point center(Point x, Point y, Point z) { + double a1 = y.x - x.x, a2 = z.x - x.x, b1 = y.y - x.y, b2 = z.y - x.y, + c1 = (a1 * a1 + b1 * b1) / 2, c2 = (a2 * a2 + b2 * b2) / 2, + d = a1 * b2 - a2 * b1; + return (Point) {x.x + (c1 * b2 - c2 * b1) / d, x.y + (a1 * c2 - a2 * c1) / d}; +} +void cal(int n, Point b[]) { + O = a[0]; R = 0; + for (int i = 0; i < n; i++) { a[i] = b[i]; } + for (int i = 0; i < n; i++) { swap(a[rand() % n], a[i]); } + for (int i = 1; i < n; i++) { + if (dis(a[i], O) > R + EPS) { + O = a[i]; R = 0; + for (int j = 0; j < i; j++) { + if (dis(a[j], O) > R + EPS) { + O = (Point) {(a[i].x + a[j].x) / 2, (a[i].y + a[j].y) / 2}, R = dis(O, a[i]); + for (int k = 0; k < j; k++) { + if (dis(a[k], O) > R + EPS) { O = center(a[k], a[j], a[i]), R = dis(O, a[i]); } + } + } + } + } + } +} + +//kuangbin +//1 +//1.1 Point +const double PI = acos(-1.0); +const double EPS = 1e-8; +inline int sgn(double x) { + return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1)); +} +struct Point { + double x, y; + Point() {} + Point(double _x, double _y): x(_x), y(_y) {} + Point operator-(const Point &b)const { + return Point(x - b.x, y - b.y); + } + // + double operator^(const Point &b)const { + return x * b.y - y * b.x; + } + // + double operator*(const Point &b)const { + return x * b.x + y * b.y; + } + //ԭתǶB(ֵ), x, yı仯 + void transXY(double B) { + double tx = x, ty = y; + x = tx * cos(B) - ty * sin(B); + y = tx * sin(B) + ty * cos(B); + } +}; +//1.2 Line +struct Line { + Point s, e; + Line() {} + Line(Point _s, Point _e): s(_s), e(_e) {} + //ֱཻ󽻵 + //һֵΪ0ʾֱغ, Ϊ1ʾƽ, Ϊ0ʾཻ, Ϊ2ཻ + //ֻеһֵΪ2ʱ, + pair operator&(const Line &b)const { + Point res = s; + if (sgn((s - e) ^ (b.s - b.e)) == 0) { + if (sgn((s - b.e) ^ (b.s - b.e)) == 0) { return make_pair(0, res); } //غ + else { return make_pair(1, res); } //ƽ + } + double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e)); + res.x += (e.x - s.x) * t; + res.y += (e.y - s.y) * t; + return make_pair(2, res); + } +}; +//1.3 +//* +double dist(const Point &a, const Point &b) { + return sqrt((a - b) * (a - b)); +} +//1.4 ж: ߶ཻ +//*ж߶ཻ +bool inter(const Line &l1, const Line &l2) { + return max(l1.s.x, l1.e.x) >= min(l2.s.x, l2.e.x) + && max(l2.s.x, l2.e.x) >= min(l1.s.x, l1.e.x) + && max(l1.s.y, l1.e.y) >= min(l2.s.y, l2.e.y) + && max(l2.s.y, l2.e.y) >= min(l1.s.y, l1.e.y) + && sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) <= 0 + && sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e-l2.e) ^ (l2.s - l2.e)) <= 0; +} +//1.5 жϣֱߺ߶ཻ +//жֱߺ߶ཻ +bool Seg_inter_line(const Line &l1, const Line &l2) { //жֱl1߶l2Ƿཻ + return sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) <= 0; +} +//1.6 㵽ֱ߾ +//㵽ֱ߾ +//Ϊresult, ǵ㵽ֱĵ +Point PointToLine(const Point &P, const Line &L) { + double t = ((P - L.s) * (L.e-L.s)) / ((L.e - L.s) * (L.e - L.s)); + return Point(L.s.x + (L.e.x - L.s.x) * t, L.s.y + (L.e.y - L.s.y) * t); +} +//1.7 㵽߶ξ +//㵽߶εľ +//ص㵽߶ĵ +Point NearestPointToLineSeg(const Point &P, const Line &L) { + double t = ((P - L.s) * (L.e-L.s)) / ((L.e-L.s) * (L.e-L.s)); + Point result; + if (t >= 0 && t <= 1) { + result.x = L.s.x + (L.e.x - L.s.x) * t; + result.y = L.s.y + (L.e.y - L.s.y) * t; + } else { + if (dist(P, L.s) < dist(P, L.e)) { result = L.s; } + else { result = L.e; } + } + return result; +} +//1.8 +// +//ıŴ0 ~ n - 1 +double CalcArea(Point p[], int n) { + double res = 0; + for (int i = 0; i < n; i++) { + res += (p[i] ^ p[(i + 1) % n]) * 0.5; + } + return fabs(res); +} +//1.9 жϵ߶ +//*жϵ߶ +bool OnSeg(const Point &P, const Line &L) { + return sgn((L.s - P) ^ (L.e-P)) == 0 + && sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 + && sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0; +} +//1.10 жϵ͹ +//*жϵ͹ +//γһ͹, Ұʱ(˳ʱ<0Ϊ>0) +//ı:0 ~ n - 1 +//ֵ: +//-1:͹ +//0:͹α߽ +//1:͹ +int inConvexPoly(const Point &a, Point p[], int n) { + for (int i = 0; i < n; i++) { + if (sgn((p[i] - a) ^ (p[(i + 1) % n] - a)) < 0) { return -1; } + else if (OnSeg(a, Line(p[i], p[(i + 1) % n]))) { return 0; } + } + return 1; +} +//1.11 жϵ +//*жϵ +//߷, poly[]ĶҪڵ3,ı0~n-1 +//ֵ +//-1:͹ +//0:͹α߽ +//1:͹ +int inPoly(const Point &p, Point poly[], int n) { + int cnt = 0; + Line ray(p, Point(-100000000000.0, p.y)), side; //-INF,עȡֵֹԽ + for (int i = 0; i < n; i++) { + side.s = poly[i]; + side.e = poly[(i + 1) % n]; + if (OnSeg(p, side)) { return 0; } + //ƽ򲻿 + if (sgn(side.s.y - side.e.y) == 0) { continue; } + if (OnSeg(side.s, ray)) { + if (sgn(side.s.y - side.e.y) > 0) { cnt++; } + } else if (OnSeg(side.e, ray)) { + if (sgn(side.e.y - side.s.y) > 0) { cnt++; } + } else if (inter(ray, side)) { + cnt++; + } + } + if (cnt & 1) { return 1; } + else { return -1; } +} +//1.12 ж͹ +//ж͹ +//߱ +//˳ʱҲʱ +//ı1~n-1 +bool isconvex(Point poly[], int n) { + bool s[3] = {0}; + for (int i = 0; i < n; i++) { + s[sgn((poly[(i + 1) % n] - poly[i]) ^ (poly[(i + 2) % n] - poly[i])) + 1] = true; + if (s[0] && s[2]) { return false; } + } + return true; +} +//2͹ +/* +* ͹, Graham㷨 +* ı0 ~ n - 1 +* ͹Stack[0 ~ top - 1]Ϊ͹ı +*/ +const int N = 1010; +Point lst[N]; +int Stack[N], top; +//lst[0]ļ +bool _cmp(const Point &p1, const Point &p2) { + double tmp = (p1 - lst[0]) ^ (p2 - lst[0]); + if (sgn(tmp) > 0) { return true; } + else if (sgn(tmp) == 0 && sgn(dist(p1, lst[0]) - dist(p2, lst[0])) <= 0) { return true; } + else { return false; } +} +void Graham(int n) { + Point p0 = lst[0]; + int k = 0; + //±ߵһ + for (int i = 1; i < n; i++) { + if ((p0.y > lst[i].y) || (p0.y == lst[i].y && p0.x > lst[i].x)) { + p0 = lst[i]; k = i; + } + } + swap(lst[k], lst[0]); + sort(lst + 1, lst + n, _cmp); + if (n == 1) { + top = 1; + Stack[0] = 0; + return; + } + if (n == 2) { + top = 2; + Stack[0] = 0; + Stack[1] = 1; + return ; + } + top = 2; + Stack[0] = 0; + Stack[1] = 1; + for (int i = 2; i < n; i++) { + while (top > 1 && sgn((lst[Stack[top - 1]] - lst[Stack[top - 2]]) ^ (lst[i] - lst[Stack[top - 2]])) <= 0) { + top--; + } + Stack[top++] = i; + } +} +//3ƽ(HDU 1007) +const double EPS = 1e-6; +const double INF = 1e20; +const int N = 100005; +struct Point { + double x, y; +} p[N], tmpt[N]; +double dist(const Point &a, const Point &b) { + return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); +} +bool cmpxy(const Point &a, const Point &b) { + return a.x < b.x || (a.x == b.x && a.y < b.y); +} +bool cmpy(Point a, Point b) { + return a.y < b.y; +} +double Closest_Pair(int left, int right) { + double d = INF; + if (left == right) { return d; } + if (left + 1 == right) { return dist(p[left], p[right]); } + int mid = (left + right) / 2; + double d1 = Closest_Pair(left, mid); + double d2 = Closest_Pair(mid + 1, right); + d = min(d1, d2); + int k = 0; + for (int i = left; i <= right; i++) { + if (fabs(p[mid].x - p[i].x) <= d) { + tmpt[k++] = p[i]; + } + } + sort(tmpt, tmpt + k, cmpy); + for (int i = 0; i < k; i++) { + for (int j = i + 1; j < k && tmpt[j].y - tmpt[i].y < d; j++) { + d = min(d, dist(tmpt[i], tmpt[j])); + } + } + return d; +} +int main() { + int n; + while (scanf("%d", &n) == 1 && n) { + for (int i = 0; i < n; i++) { + scanf("%lf%lf", &p[i].x, &p[i].y); + } + sort(p, p + n, cmpxy); + printf("%.2lf\n", Closest_Pair(0, n - 1) / 2); + } +} +//4ת +//4.1 ƽԶ(POJ 2187 Beauty Contest) +struct Point { + int x, y; + Point(int _x = 0, int _y = 0): x(_x), y(_y) {} + Point operator-(const Point &b)const { + return Point(x - b.x, y - b.y); + } + int operator^(const Point &b)const { + return x * b.y - y * b.x; + } + int operator*(const Point &b)const { + return x * b.x + y * b.y; + } + void input() { + scanf("%d%d", &x, &y); + } +}; +//ƽ +int dist2(const Point &a, const Point &b) { + return (a - b) * (a - b); +} +//******ά͹, int*********** +const int N = 50005; +Point lst[N], p[N]; +int Stack[N], top; +bool _cmp(const Point &p1, const Point &p2) { + int tmp = (p1 - lst[0]) ^ (p2 - lst[0]); + if (tmp > 0) { return true; } + else if (tmp == 0 && dist2(p1, lst[0]) <= dist2(p2, lst[0])) { return true; } + else { return false; } +} +void Graham(int n) { + Point p0 = lst[0]; + int k = 0; + for (int i = 1; i < n; i++) { + if (p0.y > lst[i].y || (p0.y == lst[i].y && p0.x > lst[i].x)) { + p0 = lst[i]; + k = i; + } + } + swap(lst[k], lst[0]); + sort(lst + 1, lst + n, _cmp); + if (n == 1) { + top = 1; + Stack[0] = 0; + return; + } + if (n == 2) { + top = 2; + Stack[0] = 0; Stack[1] = 1; + return; + } + top = 2; + Stack[0] = 0; + Stack[1] = 1; + for (int i = 2; i < n; i++) { + while (top > 1 && ((lst[Stack[top - 1]] - lst[Stack[top - 2]]) ^ (lst[i] - lst[Stack[top - 2]])) <= 0) { + top--; + } + Stack[top++] = i; + } +} +//ת, ƽֵ +int rotating_calipers(Point p[], int n) { + int ans = 0, cur = 1; + Point v; + for (int i = 0; i < n; i++) { + v = p[i] - p[(i + 1) % n]; + while ((v ^ (p[(cur + 1) % n] - p[cur])) < 0) { + cur = (cur + 1) % n; + } + ans = max(ans, max(dist2(p[i], p[cur]), dist2(p[(i + 1) % n], p[(cur + 1) % n]))); + } + return ans; +} +int main() { + int n; + while (~scanf("%d", &n)) { + for (int i = 0; i < n; i++) { lst[i].input(); } + Graham(n); + for (int i = 0; i < top; i++) { p[i] = lst[Stack[i]]; } + printf("%d\n", rotating_calipers(p, top)); + } +} +//4.2 ƽ㼯 +//תǼƽ㼯 +Point lst[N], p[N]; +int rotating_calipers(Point p[], int n) { + int ans = 0; + Point v; + for (int i = 0; i < n; i++) { + int j = (i + 1) % n, k = (j + 1) % n; + while (j != i && k != i) { + ans = max(ans, abs((p[j] - p[i]) ^ (p[k] - p[i]))); + while (((p[i] - p[j]) ^ (p[(k + 1) % n] - p[k])) < 0) { + k = (k + 1) % n; + } + j = (j + 1) % n; + } + } + return ans; +} +int main() { + int n; + while (scanf("%d", &n) == 1) { + if (n == -1) { break; } + for (int i = 0; i < n; i++) { lst[i].input(); } + Graham(n); + for (int i = 0; i < top; i++) { p[i] = lst[Stack[i]]; } + printf("%.2f\n", rotating_calipers(p, top) / 2.0); + } +} +//4.3 ͹С(POJ 3608) +const double EPS = 1e-8; +inline int sgn(double x) { + return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1)); +} +struct Point { + double x, y; + Point() {} + Point(double _x = 0, double _y = 0): x(_x), y(_y) {} + Point operator-(const Point &b)const { + return Point(x - b.x, y - b.y); + } + // + double operator^(const Point &b)const { + return x * b.y - y * b.x; + } + // + double operator*(const Point &b)const { + return x * b.x + y * b.y; + } + void input() { + scanf("%lf%lf", &x, &y); + } +}; +struct Line { + Point s, e; + Line() {} + Line(Point _s, Point _e): s(_s), e(_e) {} +}; +// +double dist(const Point &a, const Point &b) { + return sqrt((a - b) * (a - b)); +} +//㵽߶εľ, ص㵽߶ĵ +Point NearestPointToLineSeg(const Point &P, const Line &L) { + double t = ((P - L.s) * (L.e-L.s)) / ((L.e-L.s) * (L.e-L.s)); + Point result; + if (t >= 0 && t <= 1) { + result.x = L.s.x + (L.e.x - L.s.x) * t; + result.y = L.s.y + (L.e.y - L.s.y) * t; + } else { + if (dist(P, L.s) < dist(P, L.e)) { result = L.s; } + else { result = L.e; } + } + return result; +} +/* +* ͹, Graham㷨 +* ı0~n-1 +* ͹Stack[0~top-1]Ϊ͹ı +*/ +const int N = 10005; +Point lst[N]; +int Stack[N], top; +//list[0]ļ +bool _cmp(const Point &p1, const Point &p2) { + double tmp = (p1 - lst[0]) ^ (p2 - lst[0]); + if (sgn(tmp) > 0) { return true; } + else if (sgn(tmp) == 0 && sgn(dist(p1, lst[0]) - dist(p2, lst[0])) <= 0) { return true; } + else { return false; } +} +void Graham(int n) { + Point p0 = lst[0]; + int k = 0; + //±ߵһ + for (int i = 1; i < n; i++) { + if ((p0.y > lst[i].y) || (p0.y == lst[i].y && p0.x > lst[i].x)) { + p0 = lst[i]; + k = i; + } + } + swap(lst[k], lst[0]); + sort(lst + 1, lst + n, _cmp); + if (n == 1) { + top = 1; + Stack[0] = 0; + return; + } + if (n == 2) { + top = 2; + Stack[0] = 0; + Stack[1] = 1; + return ; + } + top = 2; + Stack[0] = 0; + Stack[1] = 1; + for (int i = 2; i < n; i++) { + while (top > 1 && sgn((lst[Stack[top - 1]] - lst[Stack[top - 2]]) ^ (lst[i] - lst[Stack[top - 2]])) <= 0) { + top--; + } + Stack[top++] = i; + } +} +//p0߶p1p2ľ +double pointtoseg(const Point &p0, const Point &p1, const Point &p2) { + return dist(p0, NearestPointToLineSeg(p0, Line(p1, p2))); +} +//ƽ߶p0p1p2p3ľ +double dispallseg(const Point &p0, const Point &p1, const Point &p2, const Point &p3) { + double ans1 = min(pointtoseg(p0, p2, p3), pointtoseg(p1, p2, p3)); + double ans2 = min(pointtoseg(p2, p0, p1), pointtoseg(p3, p0, p1)); + return min(ans1, ans2); +} +//õa1a2b1b2λùϵ +double Get_angle(const Point &a1, const Point &a2, const Point &b1, const Point &b2) { + return (a2 - a1) ^ (b1 - b2); +} +double rotating_calipers(Point p[], int np, Point q[], int nq) { + int sp = 0, sq = 0; + for (int i = 0; i < np; i++) { + if (sgn(p[i].y - p[sp].y) < 0) { sp = i; } + } + for (int i = 0; i < nq; i++) { + if (sgn(q[i].y - q[sq].y) > 0) { sq = i; } + } + double ans = dist(p[sp], q[sq]), tmp; + for (int i = 0; i < np; i++) { + while (sgn(tmp = Get_angle(p[sp], p[(sp + 1) % np], q[sq], q[(sq + 1) % nq])) < 0) { + sq = (sq + 1) % nq; + } + if (sgn(tmp) == 0) { + ans = min(ans, dispallseg(p[sp], p[(sp + 1) % np], q[sq], q[(sq + 1) % nq])); + } else { ans = min(ans, pointtoseg(q[sq], p[sp], p[(sp + 1) % np])); } + sp = (sp + 1) % np; + } + return ans; +} +double solve(Point p[], int n, Point q[], int m) { + return min(rotating_calipers(p, n, q, m), rotating_calipers(q, m, p, n)); +} +Point p[N], q[N]; +int main() { + int n, m; + while (scanf("%d%d", &n, &m) == 2) { + if (n == 0 && m == 0) { break; } + for (int i = 0; i < n; i++) { lst[i].input(); } + Graham(n); + for (int i = 0; i < top; i++) { p[i] = lst[i]; } + n = top; + for (int i = 0; i < m; i++) { lst[i].input(); } + Graham(m); + for (int i = 0; i < top; i++) { q[i] = lst[i]; } + m = top; + printf("%.4f\n", solve(p, n, q, m)); + } +} +//5ƽ潻 +//5.1 ƽ潻ģ(from UESTC) +const double PI = acos(-1.0); +const double EPS = 1e-8; +const int N = 105; +inline int sgn(double x) { + return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1)); +} +struct Point { + double x, y; + Point() {} + Point(double _x, double _y): x(_x), y(_y) {} + Point operator-(const Point &b)const { + return Point(x - b.x, y - b.y); + } + double operator^(const Point &b)const { + return x * b.y - y * b.x; + } + double operator*(const Point &b)const { + return x * b.x + y * b.y; + } +}; +struct Line { + Point s, e; + double k; + Line() {} + Line(Point _s, Point _e): s(_s), e(_e), k(atan2(e.y - s.y, e.x - s.x)) {} + Point operator&(const Line &b)const { + Point res = s; + double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e)); + res.x += (e.x - s.x) * t; + res.y += (e.y - s.y) * t; + return res; + } +}; +//ƽ潻, ֱߵߴЧ +bool HPIcmp(const Line &a, const Line &b) { + if (fabs(a.k - b.k) > EPS) { return a.k < b.k; } + return ((a.s - b.s) ^ (b.e - b.s)) < 0; +} +Line Q[N]; +void HPI(Line line[], int n, Point res[], int &resn) { + int tot = 1; + sort(line, line + n, HPIcmp); + for (int i = 1; i < n; i++) { + if (fabs(line[i].k - line[i - 1].k) > EPS) { line[tot++] = line[i]; } + } + int head = 0, tail = 1; + Q[0] = line[0]; Q[1] = line[1]; + resn = 0; + for (int i = 2; i < tot; i++) { + if (fabs((Q[tail].e-Q[tail].s) ^ (Q[tail - 1].e-Q[tail - 1].s)) < EPS + || fabs((Q[head].e-Q[head].s) ^ (Q[head + 1].e-Q[head + 1].s)) < EPS) { + return; + } + while (head < tail + && (((Q[tail]&Q[tail - 1]) - line[i].s) ^ (line[i].e-line[i].s)) > EPS) { + tail--; + } + while (head < tail + && (((Q[head]&Q[head + 1]) - line[i].s) ^ (line[i].e-line[i].s)) > EPS) { + head++; + } + Q[++tail] = line[i]; + } + while (head < tail + && (((Q[tail]&Q[tail - 1]) - Q[head].s) ^ (Q[head].e-Q[head].s)) > EPS) { + tail--; + } + while (head < tail + && (((Q[head]&Q[head - 1]) - Q[tail].s) ^ (Q[tail].e-Q[tail].e)) > EPS) { + head++; + } + if (tail <= head + 1) { return; } + for (int i = head; i < tail; i++) { + res[resn++] = Q[i] & Q[i + 1]; + } + if (head < tail - 1) { + res[resn++] = Q[head] & Q[tail]; + } +} +//5.2 ͨƽ潻д +//POJ 1750 +const double EPS = 1e-18; +const double INF = 100000000000.0; +const int N = 105; +inline int sgn(double x) { + return (fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1)); +} +struct Point { + double x, y; + Point() {} + Point(double _x, double _y): x(_x), y(_y) {} + Point operator-(const Point &b)const { + return Point(x - b.x, y - b.y); + } + double operator^(const Point &b)const { + return x * b.y - y * b.x; + } + double operator*(const Point &b)const { + return x * b.x + y * b.y; + } +}; +// +double CalcArea(Point p[], int n) { + double res = 0; + for (int i = 0; i < n; i++) { + res += (p[i] ^ p[(i + 1) % n]); + } + return fabs(res / 2); +} +//ͨ, ȷֱ߷ +void Get_equation(const Point &p1, const Point &p2, double &a, double &b, double &c) { + a = p2.y - p1.y; + b = p1.x - p2.x; + c = p2.x * p1.y - p1.x * p2.y; +} +//󽻵 +Point Intersection(const Point &p1, const Point &p2, double a, double b, double c) { + double u = fabs(a * p1.x + b * p1.y + c); + double v = fabs(a * p2.x + b * p2.y + c); + return Point((p1.x * v + p2.x * u) / (u + v), (p1.y * v + p2.y * u) / (u + v)); +} +Point tp[N]; +void Cut(double a, double b, double c, Point p[], int &cnt) { + int tmp = 0; + for (int i = 1; i <= cnt; i++) { + //ǰ, ʱĵ + if (a * p[i].x + b * p[i].y + c < EPS) { tp[++tmp] = p[i]; } + else { + if (a * p[i - 1].x + b * p[i - 1].y + c < -EPS) { + tp[++tmp] = Intersection(p[i - 1], p[i], a, b, c); + } + if (a * p[i + 1].x + b * p[i + 1].y + c < -EPS) { + tp[++tmp] = Intersection(p[i], p[i + 1], a, b, c); + } + } + } + for (int i = 1; i <= tmp; i++) { p[i] = tp[i]; } + p[0] = p[tmp]; + p[tmp + 1] = p[1]; + cnt = tmp; +} +double V[N], U[N], W[N]; +int n; +Point p[N]; +bool solve(int id) { + p[1] = Point(0, 0); + p[2] = Point(INF, 0); + p[3] = Point(INF, INF); + p[4] = Point(0, INF); + p[0] = p[4]; + p[5] = p[1]; + int cnt = 4; + for (int i = 0; i < n; i++) { + if (i != id) { + double a = (V[i] - V[id]) / (V[i] * V[id]); + double b = (U[i] - U[id]) / (U[i] * U[id]); + double c = (W[i] - W[id]) / (W[i] * W[id]); + if (sgn(a) == 0 && sgn(b) == 0) { + if (sgn(c) >= 0) { return false; } + else { continue; } + } + Cut(a, b, c, p, cnt); + } + } + if (sgn(CalcArea(p, cnt)) == 0) { return false; } + else { return true; } +} +int main() { + while (scanf("%d", &n) == 1) { + for (int i = 0; i < n; i++) { + scanf("%lf%lf%lf", &V[i], &U[i], &W[i]); + } + for (int i = 0; i < n; i++) { + if (solve(i)) { printf("Yes\n"); } + else { printf("No\n"); } + } + } +} +//6Բ() +//Բ +Point waixin(const Point &a, const Point &b, const Point &c) { + double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1 * a1 + b1 * b1) / 2; + double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2 * a2 + b2 * b2) / 2; + double d = a1 * b2 - a2 * b1; + return Point(a.x + (c1 * b2 - c2 * b1) / d, a.y + (a1 * c2 - a2 * c1) / d); +} +//7Բཻ +//ԲĹ +double Area_of_overlap(const Point &c1, double r1, const Point &c2, double r2) { + double d = dist(c1, c2); + if (r1 + r2 < d + EPS) { return 0; } + if (d < fabs(r1 - r2) + EPS) { + double r = min(r1, r2); + return PI * r * r; + } + double x = (d * d + r1 * r1 - r2 * r2) / (2 * d); + double t1 = acos(x / r1); + double t2 = acos((d - x) / r2); + return r1 * r1 * t1 + r2 * r2 * t2 - d * r1 * sin(t1); +} +//8Pick ʽ +//ļ򵥶: = ڲĿ + ϸĿ / 2 - 1 + + + +//http://www.cppblog.com/abilitytao/archive/2009/08/04/92171.html + +// +const double M_PI = acos(-1.0); //PI +const double INF = 1e10; // +const double EPS = 1e-8; //㾫 +const int LEFT = 0; //ֱ +const int RIGHT = 1; //ֱұ +const int ONLINE = 2; //ֱ +const int CROSS = 0; //ֱཻ +const int COLINE = 1; //ֱ߹ +const int PARALLEL = 2; //ֱƽ +const int NOTCOPLANAR = 3; //ֱ߲ +const int INSIDE = 1; //ͼڲ +const int OUTSIDE = 2; //ͼⲿ +const int BORDER = 3; //ͼα߽ +const int BAOHAN = 1; //ԲСԲ +const int NEIQIE = 2; // +const int XIANJIAO = 3; //ཻ +const int WAIQIE = 4; // +const int XIANLI = 5; // +/////////////////////////////////////////////////////////////////// +//Ͷ +struct Point { //άʸ + double x, y; + double angle, dis; + Point(): x(0), y(0), angle(0), dis(0) {} + Point(double x0, double y0): x(x0), y(y0), angle(0), dis(0) {} +}; +struct Point3D { //άʸ + double x, y, z; + Point3D(): x(0), y(0), z(0) {} + Point3D(double x0, double y0, double z0): x(x0), y(y0), z(z0) {} +}; +struct Line { //άֱ߻߶ + Point p1, p2; + Line(): p1(), p2() {} + Line(Point p10, Point p20): p1(p10), p2(p20) {} +}; +struct Line3D { //άֱ߻߶ + Point3D p1, p2; + Line3D(): p1(), p2() {} + Line3D(Point3D p10, Point3D p20): p1(p10), p2(p20) {} +}; +struct Rect { //óʾεķ w, hֱʾȺ͸߶ + double w, h; + Rect(): w(0), h(0) {} + Rect(double _w, double _h) : w(_w), h(_h) {} +}; +struct Rect_2 { //ʾ, ½(xl, yl), Ͻ(xh, yh) + double xl, yl, xh, yh; + Rect_2(): xl(0), yl(0), xh(0), yh(0) {} + Rect_2(double _xl, double _yl, double _xh, double _yh) : xl(_xl), yl(_yl), xh(_xh), yh(_yh) {} +}; +struct Circle { //Բ + Point c; + double r; + Circle(): c(), r(0) {} + Circle(Point _c, double _r) : c(_c), r(_r) {} +}; +typedef vector Polygon; //ά +typedef vector Points; //ά㼯 +typedef vector Points3D; //ά㼯 +/////////////////////////////////////////////////////////////////// +// +inline bool ZERO(double x) { //x == 0 + return (fabs(x) < EPS); +} +inline bool ZERO(Point p) { //p == 0 + return (ZERO(p.x) && ZERO(p.y)); +} +inline bool ZERO(Point3D p) { //p == 0 + return (ZERO(p.x) && ZERO(p.y) && ZERO(p.z)); +} +inline bool EQ(double x, double y) { //eqaul, x == y + return (fabs(x - y) < EPS); +} +inline bool NEQ(double x, double y) { //not equal, x != y + return (fabs(x - y) >= EPS); +} +inline bool LT(double x, double y) { //less than, x < y + return (NEQ(x, y) && (x < y)); +} +inline bool GT(double x, double y) { //greater than, x > y + return (NEQ(x, y) && (x > y)); +} +inline bool LEQ(double x, double y) { //less equal, x <= y + return (EQ(x, y) || (x < y)); +} +inline bool GEQ(double x, double y) { //greater equal, x >= y + return (EQ(x, y) || (x > y)); +} +//ע⣡ +//һСĸĸ +//Чλʱ-0.000ʽ, +//ǰһ +//ͻᵼ´󣡣 +//֮ǰ, һҪôκ +inline double FIX(double x) { + return (fabs(x) < EPS) ? 0 : x; +} +///////////////////////////////////////////////////////////////////////////////////// +//άʸ +bool operator==(Point p1, Point p2) { + return (EQ(p1.x, p2.x) && EQ(p1.y, p2.y)); +} +bool operator!=(Point p1, Point p2) { + return (NEQ(p1.x, p2.x) || NEQ(p1.y, p2.y)); +} +bool operator<(Point p1, Point p2) { + if (NEQ(p1.x, p2.x)) { return (p1.x < p2.x); } + else { return (p1.y < p2.y); } +} +Point operator+(Point p1, Point p2) { + return Point(p1.x + p2.x, p1.y + p2.y); +} +Point operator-(Point p1, Point p2) { + return Point(p1.x - p2.x, p1.y - p2.y); +} +double operator*(Point p1, Point p2) { // p1 p2 + return (p1.x * p2.y - p2.x * p1.y); +} +double operator&(Point p1, Point p2) { // p1p2 + return (p1.x * p2.x + p1.y * p2.y); +} +double Norm(Point p) { //ʸpģ + return sqrt(p.x * p.x + p.y * p.y); +} +//ʸpתǶangle (ȱʾ) +//angle > 0ʾʱת +//angle < 0ʾ˳ʱת +Point Rotate(Point p, double angle) { + Point result; + result.x = p.x * cos(angle) - p.y * sin(angle); + result.y = p.x * sin(angle) + p.y * cos(angle); + return result; +} +////////////////////////////////////////////////////////////////////////////////////// +//άʸ +bool operator==(Point3D p1, Point3D p2) { + return (EQ(p1.x, p2.x) && EQ(p1.y, p2.y) && EQ(p1.z, p2.z)); +} +bool operator<(Point3D p1, Point3D p2) { + if (NEQ(p1.x, p2.x)) { return (p1.x < p2.x); } + else if (NEQ(p1.y, p2.y)) { return (p1.y < p2.y); } + else { return (p1.z < p2.z); } +} +Point3D operator+(Point3D p1, Point3D p2) { + return Point3D(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z); +} +Point3D operator-(Point3D p1, Point3D p2) { + return Point3D(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z); +} +Point3D operator*(Point3D p1, Point3D p2) { // p1 x p2 + return Point3D(p1.y * p2.z - p1.z * p2.y, p1.z * p2.x - p1.x * p2.z, p1.x * p2.y - p1.y * p2.x); +} +double operator&(Point3D p1, Point3D p2) { // p1p2 + return (p1.x * p2.x + p1.y * p2.y + p1.z * p2.z); +} +double Norm(Point3D p) { //ʸpģ + return sqrt(p.x * p.x + p.y * p.y + p.z * p.z); +} +///////////////////////////////////////////////////////////////////////////////////// +// +// +// +//ȷ +double Area(Point A, Point B, Point C) { // + return ((B - A) * (C - A) / 2.0); +} +//߳ +double Area(double a, double b, double c) { // + double s = (a + b + c) / 2.0; + return sqrt(s * (s - a) * (s - b) * (s - c)); +} +double Area(const Circle &C) { + return M_PI * C.r * C.r; +} +// +//ȷ +double Area(const Polygon &poly) { // + double res = 0; + int n = poly.size(); + if (n < 3) { return 0; } + for (int i = 0; i < n; i++) { + res += poly[i].x * poly[(i + 1) % n].y; + res -= poly[i].y * poly[(i + 1) % n].x; + } + return (res / 2.0); +} +///////////////////////////////////////////////////////////////////////////////////// +//.߶.ֱ +// +double Distance(Point p1, Point p2) { //2ľ + return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); +} +double Distance(Point3D p1, Point3D p2) { //2ľ,ά + return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)); +} +double Distance(Point p, Line L) { //άƽϵ㵽ֱߵľ + return (fabs((p - L.p1) * (L.p2 - L.p1)) / Norm(L.p2 - L.p1)); +} +double Distance(Point3D p, Line3D L) { //άռе㵽ֱߵľ + return (Norm((p - L.p1) * (L.p2 - L.p1)) / Norm(L.p2 - L.p1)); +} +bool OnLine(Point p, Line L) { //ж϶άƽϵpǷֱL + return ZERO((p - L.p1) * (L.p2 - L.p1)); +} +bool OnLine(Point3D p, Line3D L) { //жάռеpǷֱL + return ZERO((p - L.p1) * (L.p2 - L.p1)); +} +int Relation(Point p, Line L) { //pֱLԹϵ ,ONLINE,LEFT,RIGHT + double res = (L.p2 - L.p1) * (p - L.p1); + if (EQ(res, 0)) { return ONLINE; } + else if (res > 0) { return LEFT; } + else { return RIGHT; } +} +bool SameSide(Point p1, Point p2, Line L) { //жϵp1, p2ǷֱLͬ + double m1 = (p1 - L.p1) * (L.p2 - L.p1); + double m2 = (p2 - L.p1) * (L.p2 - L.p1); + return GT(m1 * m2, 0); +} +bool OnLineSeg(Point p, Line L) { //ж϶άƽϵpǷ߶l + return (ZERO((L.p1 - p) * (L.p2 - p)) && LEQ((p.x - L.p1.x) * (p.x - L.p2.x), 0) + && LEQ((p.y - L.p1.y) * (p.y - L.p2.y), 0)); +} +bool OnLineSeg(Point3D p, Line3D L) { //жάռеpǷ߶l + return (ZERO((L.p1 - p) * (L.p2 - p)) && EQ(Norm(p - L.p1) + Norm(p - L.p2), Norm(L.p2 - L.p1))); +} +Point SymPoint(Point p, Line L) { //άƽϵpֱLĶԳƵ + Point result; + double a = L.p2.x - L.p1.x; + double b = L.p2.y - L.p1.y; + double t = ((p.x - L.p1.x) * a + (p.y - L.p1.y) * b) / (a * a + b * b); + result.x = 2 * L.p1.x + 2 * a * t - p.x; + result.y = 2 * L.p1.y + 2 * b * t - p.y; + return result; +} +bool Coplanar(Points3D points) { //жһ㼯еĵǷȫ + Point3D p; + if (points.size() < 4) { return true; } + p = (points[2] - points[0]) * (points[1] - points[0]); + for (size_t i = 3; i < points.size(); i++) { + if (!ZERO(p & (points[i] - points[0]))) { return false; } + } + return true; +} +bool LineIntersect(Line L1, Line L2) { //ж϶άֱǷཻ + return (!ZERO((L1.p1 - L1.p2) * (L2.p1 - L2.p2))); //Ƿƽ +} +bool LineIntersect(Line3D L1, Line3D L2) { //жάֱǷཻ + Point3D p1 = L1.p1 - L1.p2; + Point3D p2 = L2.p1 - L2.p2; + Point3D p = p1 * p2; + if (ZERO(p)) { return false; } //Ƿƽ + p = (L2.p1 - L1.p2) * (L1.p1 - L1.p2); + return ZERO(p & L2.p2); //Ƿ +} +bool LineSegIntersect(Line L1, Line L2) { //ж϶ά߶Ƿཻ + return (GEQ(max(L1.p1.x, L1.p2.x), min(L2.p1.x, L2.p2.x)) && + GEQ(max(L2.p1.x, L2.p2.x), min(L1.p1.x, L1.p2.x)) && + GEQ(max(L1.p1.y, L1.p2.y), min(L2.p1.y, L2.p2.y)) && + GEQ(max(L2.p1.y, L2.p2.y), min(L1.p1.y, L1.p2.y)) && + LEQ(((L2.p1 - L1.p1) * (L1.p2 - L1.p1)) * ((L2.p2 - L1.p1) * (L1.p2 - L1.p1)), 0) && + LEQ(((L1.p1 - L2.p1) * (L2.p2 - L2.p1)) * ((L1.p2 - L2.p1) * (L2.p2 - L2.p1)), 0)); +} +bool LineSegIntersect(Line3D L1, Line3D L2) { //жά߶Ƿཻ + //todo + return true; +} +//άֱߵĽ, ڲPз +//ֵ˵ֱߵλùϵ: COLINE -- PARALLEL -- ƽ CROSS -- ཻ +int CalCrossPoint(Line L1, Line L2, Point &P) { + double A1, B1, C1, A2, B2, C2; + A1 = L1.p2.y - L1.p1.y; + B1 = L1.p1.x - L1.p2.x; + C1 = L1.p2.x * L1.p1.y - L1.p1.x * L1.p2.y; + A2 = L2.p2.y - L2.p1.y; + B2 = L2.p1.x - L2.p2.x; + C2 = L2.p2.x * L2.p1.y - L2.p1.x * L2.p2.y; + if (EQ(A1 * B2, B1 * A2)) { + if (EQ((A1 + B1) * C2, (A2 + B2) * C1)) { return COLINE; } + else { return PARALLEL; } + } else { + P.x = (B2 * C1 - B1 * C2) / (A2 * B1 - A1 * B2); + P.y = (A1 * C2 - A2 * C1) / (A2 * B1 - A1 * B2); + return CROSS; + } +} +//άֱߵĽ, ڲPз +//ֵ˵ֱߵλùϵ COLINE -- PARALLEL -- ƽ CROSS -- ཻ NONCOPLANAR -- +int CalCrossPoint(Line3D L1, Line3D L2, Point3D &P) { + //todo + return 0; +} +//PֱL +Point NearestPointToLine(Point P, Line L) { + Point result; + double a, b, t; + a = L.p2.x - L.p1.x; + b = L.p2.y - L.p1.y; + t = ((P.x - L.p1.x) * a + (P.y - L.p1.y) * b) / (a * a + b * b); + result.x = L.p1.x + a * t; + result.y = L.p1.y + b * t; + return result; +} +//P߶L +Point NearestPointToLineSeg(Point P, Line L) { + Point result; + double a, b, t; + a = L.p2.x - L.p1.x; + b = L.p2.y - L.p1.y; + t = ((P.x - L.p1.x) * a + (P.y - L.p1.y) * b) / (a * a + b * b); + if (GEQ(t, 0) && LEQ(t, 1)) { + result.x = L.p1.x + a * t; + result.y = L.p1.y + b * t; + } else { + if (Norm(P - L.p1) < Norm(P - L.p2)) { result = L.p1; } + else { result = L.p2; } + } + return result; +} +//նL1߶L2̾ +double MinDistance(Line L1, Line L2) { + double d1, d2, d3, d4; + if (LineSegIntersect(L1, L2)) { + return 0; + } else { + d1 = Norm(NearestPointToLineSeg(L1.p1, L2) - L1.p1); + d2 = Norm(NearestPointToLineSeg(L1.p2, L2) - L1.p2); + d3 = Norm(NearestPointToLineSeg(L2.p1, L1) - L2.p1); + d4 = Norm(NearestPointToLineSeg(L2.p2, L1) - L2.p2); + return min(min(d1, d2), min(d3, d4)); + } +} +//άֱߵļн, +//ֵ0~Pi֮Ļ +double Inclination(Line L1, Line L2) { + Point u = L1.p2 - L1.p1; + Point v = L2.p2 - L2.p1; + return acos((u & v) / (Norm(u) * Norm(v))); +} +//άֱߵļн, +//ֵ0~Pi֮Ļ +double Inclination(Line3D L1, Line3D L2) { + Point3D u = L1.p2 - L1.p1; + Point3D v = L2.p2 - L2.p1; + return acos((u & v) / (Norm(u) * Norm(v))); +} +///////////////////////////////////////////////////////////////////////////// +//: +//жϵpǷ͹poly +//polyĶĿҪڵ3 +//ֵΪ +//INSIDE -- poly +//BORDER -- poly߽ +//OUTSIDE -- poly +int InsideConvex(Point p, const Polygon &poly) { //жϵpǷ͹poly + Point q(0, 0); + Line side; + int i, n = poly.size(); + for (i = 0; i < n; i++) { + q.x += poly[i].x; q.y += poly[i].y; + } + q.x /= n; q.y /= n; + for (i = 0; i < n; i++) { + side.p1 = poly[i]; + side.p2 = poly[(i + 1) % n]; + if (OnLineSeg(p, side)) { return BORDER; } + else if (!SameSide(p, q, side)) { return OUTSIDE; } + } + return INSIDE; +} +//ж϶polyǷ͹ +bool IsConvex(const Polygon &poly) { + int i, n, rel; + Line side; + n = poly.size(); + if (n < 3) { return false; } + side.p1 = poly[0]; + side.p2 = poly[1]; + rel = Relation(poly[2], side); + for (i = 1; i < n; i++) { + side.p1 = poly[i]; + side.p2 = poly[(i + 1) % n]; + if (Relation(poly[(i + 2) % n], side) != rel) { return false; } + } + return true; +} +//жϵpǷڼ򵥶poly, ο͹Ļ򰼵 +//polyĶĿҪڵ3 +//ֵΪ +//INSIDE -- poly +//BORDER -- poly߽ +//OUTSIDE -- poly +int InsidePolygon(const Polygon &poly, Point p) { + int i, n, count; + Line ray, side; + n = poly.size(); + count = 0; + ray.p1 = p; + ray.p2.y = p.y; + ray.p2.x = - INF; + for (i = 0; i < n; i++) { + side.p1 = poly[i]; + side.p2 = poly[(i + 1) % n]; + if (OnLineSeg(p, side)) { + return BORDER; + } + //sideƽx + if (EQ(side.p1.y, side.p2.y)) { continue; } + if (OnLineSeg(side.p1, ray)) { + if (GT(side.p1.y, side.p2.y)) { count++; } + } else if (OnLineSeg(side.p2, ray)) { + if (GT(side.p2.y, side.p1.y)) { count++; } + } else if (LineSegIntersect(ray, side)) { + count++; + } + } + return ((count % 2 == 1) ? INSIDE : OUTSIDE); +} +//ж߶Ƿڶ (߶εĵڶ) +//ο򵥶 +bool InsidePolygon(const Polygon &poly, Line L) { + bool result; + int n; + Points points; + Point p; + Line side; + result = ((InsidePolygon(poly, L.p1) != OUTSIDE) && (InsidePolygon(poly, L.p2) != OUTSIDE)); + if (!result) { return false; } + n = poly.size(); + for (int i = 0; i < n; i++) { + side.p1 = poly[i]; + side.p2 = poly[(i + 1) % n]; + if (OnLineSeg(L.p1, side)) { + points.push_back(L.p1); + } else if (OnLineSeg(L.p2, side)) { + points.push_back(L.p2); + } else if (OnLineSeg(side.p1, L)) { + points.push_back(side.p1); + } else if (OnLineSeg(side.p2, L)) { + points.push_back(side.p2); + } else if (LineSegIntersect(side, L)) { + return false; + } + } + //Խ + sort(points.begin(), points.end()); + for (size_t i = 1; i < points.size(); i++) { + if (points[i - 1] != points[i]) { + p.x = (points[i - 1].x + points[i].x) / 2.0; + p.y = (points[i - 1].y + points[i].y) / 2.0; + if (InsidePolygon(poly, p) == OUTSIDE) { + return false; + } + } + } + return true; +} +//Ѱ͹ graham ɨ跨 +//ɵĶζ㰴ʱ뷽 +bool GrahamComp(const Point &left, const Point &right) { + if (EQ(left.angle, right.angle)) { + return (left.dis < right.dis); + } else { + return (left.angle < right.angle); + } +} +void GrahamScan(Points &points, Polygon &result) { + int i, k, n; + Point p; + n = points.size(); + result.clear(); + if (n < 3) { return; } + //ѡȡpointsyСĵpoints[k], + //ĵж, ȡߵһ + k = 0; + for (i = 1; i < n; i++) { + if (EQ(points[i].y, points[k].y)) { + if (points[i].x <= points[k].x) { k = i; } + } else if (points[i].y < points[k].y) { + k = i; + } + } + swap(points[0], points[k]); + //pointsyСĵpoints[0] + //ÿpoints[0]ļǺ; + for (i = 1; i < n; i++) { + points[i].angle = atan2(points[i].y - points[0].y, points[i].x - points[0].x); + points[i].dis = Norm(points[i] - points[0]); + } + //Զ㰴points[0]ļǴС + //ڼͬİվpoints[0]ľС + sort(points.begin() + 1, points.end(), GrahamComp); + //͹ + result.push_back(points[0]); + for (i = 1; i < n; i++) { + //мͬĵ, ֻȡpoints[0]Զһ + if ((i + 1 < n) && EQ(points[i].angle, points[i + 1].angle)) { continue; } + if (result.size() >= 3) { + p = result[result.size() - 2]; + while (GEQ((points[i] - p) * (result.back() - p), 0)) { + result.pop_back(); + p = result[result.size() - 2]; + } + } + result.push_back(points[i]); + } +} +//ֱlineи͹, +//result[LEFT]result[RIGHT]ֱ𱣴汻иlineߺұ߲ +//result[ONLINE]ûõ, ֻΪռ +//ֵиεпڵij, +//ֵ0 ˵δи +//δиʱ, ڸֱߵҲ, result[RIGHT]ڸö, result[LEFT]ڸö +//ע⣺иĶһҪ͹, 㰴ʱ +//εĺ, ʼĺΪһܴľ, Ȼöεÿȥ +double CutConvex(const Polygon &poly, const Line &line, Polygon result[3]) { + vector points; + Line side; + Point p; + int i, n, cur, pre; + result[LEFT].clear(); + result[RIGHT].clear(); + result[ONLINE].clear(); + n = poly.size(); + if (n == 0) { return 0; } + pre = cur = Relation(poly[0], line); + for (i = 0; i < n; i++) { + cur = Relation(poly[(i + 1) % n], line); + if (cur == pre) { + result[cur].push_back(poly[(i + 1) % n]); + } else { + side.p1 = poly[i]; + side.p2 = poly[(i + 1) % n]; + CalCrossPoint(side, line, p); + points.push_back(p); + result[pre].push_back(p); + result[cur].push_back(p); + result[cur].push_back(poly[(i + 1) % n]); + pre = cur; + } + } + sort(points.begin(), points.end()); + if (points.size() < 2) { return 0; } + else { return Norm(points.front() - points.back()); } +} +//ε, ͹Ļ򰼵ļ򵥶 +//㷨һ߶ԵĶһ߼ +Point CenterOfPolygon(const Polygon &poly) { + Point p, p0, p1, p2, p3; + double m, m0; + p1 = poly[0]; + p2 = poly[1]; + p.x = p.y = m = 0; + for (size_t i = 2; i < poly.size(); i++) { + p3 = poly[i]; + p0.x = (p1.x + p2.x + p3.x) / 3.0; + p0.y = (p1.y + p2.y + p3.y) / 3.0; + m0 = p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.y * p2.x - p2.y * p3.x - p3.y * p1.x; + if (ZERO(m + m0)) { m0 += EPS; } //Ϊ˷ֹ0, m0һ + p.x = (m * p.x + m0 * p0.x) / (m + m0); + p.y = (m * p.y + m0 * p0.y) / (m + m0); + m = m + m0; + p2 = p3; + } + return p; +} +//жǷཻ +//ڲཻ +bool Intersect(Rect_2 r1, Rect_2 r2) { + return (max(r1.xl, r2.xl) < min(r1.xh, r2.xh) && max(r1.yl, r2.yl) < min(r1.yh, r2.yh)); +} +//жϾr2ǷԷھr1 +//r2ת +//ԭĸķOJϵ޹֮, +//ԼĴ +bool IsContain(Rect r1, Rect r2) { //εw > h + if (r1.w > r2.w && r1.h > r2.h) { return true; } + else { + double r = sqrt(r2.w * r2.w + r2.h * r2.h) / 2.0; + double alpha = atan2(r2.h, r2.w); + double sita = asin((r1.h / 2.0) / r); + double x = r * cos(sita - 2 * alpha); + double y = r * sin(sita - 2 * alpha); + if (x < r1.w / 2.0 && y < r1.h / 2.0 && x > 0 && y > -r1.h / 2.0) { return true; } + else { return false; } + } +} +//////////////////////////////////////////////////////////////////////// +//Բ +Point Center(const Circle &C) { //Բ + return C.c; +} +//ԲĹ +double CommonArea(const Circle &A, const Circle &B) { + double area = 0.0; + const Circle &M = (A.r > B.r) ? A : B; + const Circle &N = (A.r > B.r) ? B : A; + double D = Distance(Center(M), Center(N)); + if ((D < M.r + N.r) && (D > M.r - N.r)) { + double cosM = (M.r * M.r + D * D - N.r * N.r) / (2.0 * M.r * D); + double cosN = (N.r * N.r + D * D - M.r * M.r) / (2.0 * N.r * D); + double alpha = 2.0 * acos(cosM); + double beta = 2.0 * acos(cosN); + double TM = 0.5 * M.r * M.r * sin(alpha); + double TN = 0.5 * N.r * N.r * sin(beta); + double FM = (alpha / 360.0) * Area(M); + double FN = (beta / 360.0) * Area(N); + area = FM + FN - TM - TN; + } else if (D <= M.r - N.r) { + area = Area(N); + } + return area; +} +//жԲǷھ() +bool IsInCircle(const Circle &C, const Rect_2 &rect) { + return (GT(C.c.x - C.r, rect.xl) && LT(C.c.x + C.r, rect.xh) && GT(C.c.y - C.r, rect.yl) + && LT(C.c.y + C.r, rect.yh)); +} +//ж2Բλùϵ +//: +//BAOHAN = 1; //ԲСԲ +//NEIQIE = 2; // +//XIANJIAO = 3; //ཻ +//WAIQIE = 4; // +//XIANLI = 5; // +int CirCir(const Circle &c1, const Circle &c2) { + double dis = Distance(c1.c, c2.c); + if (LT(dis, fabs(c1.r - c2.r))) { return BAOHAN; } + if (EQ(dis, fabs(c1.r - c2.r))) { return NEIQIE; } + if (LT(dis, c1.r + c2.r) && GT(dis, fabs(c1.r - c2.r))) { return XIANJIAO; } + if (EQ(dis, c1.r + c2.r)) { return WAIQIE; } + return XIANLI; +} diff --git a/.ACM-Templates/TXTs/输入输出.txt b/.ACM-Templates/TXTs/输入输出.txt new file mode 100644 index 0000000..ba664c6 --- /dev/null +++ b/.ACM-Templates/TXTs/输入输出.txt @@ -0,0 +1,71 @@ +//رͬ +ios_base::sync_with_stdio(false); cin.tie(NULL); +//һǸ +template void read(T &x) { + char c; + while (!isdigit(c = getchar())); + for (x = 0; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } +} +//һ +template void read(T &x) { + char c; bool neg = false; + while ((c = getchar()) != '-' && !isdigit(c)); + if (c == '-') { neg = true; c = getchar(); } + for (x = 0; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } + if (neg) { x = -x; } +} +//һ(int, long long, float, double) +template void read(T &x) { + char c; bool neg = false; + while ((c = getchar()) != '-' && c != '.' && !isdigit(c)); + if (c == '-') { neg = true; c = getchar(); } + for (x = 0; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } + if (c == ' ' || c == '\n' || c == EOF) { if (neg) { x = -x; } return; } + for (T bit = 0.1; isdigit(c = getchar()); bit *= 0.1) { x += (c - '0') * bit; } + if (neg) { x = -x; } +} +//ոΪָ ȡһе +const int BUFSIZE = 1 << 20; +char BUF[BUFSIZE]; +void readln(int a[]) { + int i = 0; gets(BUF); + for (char *p = strtok(BUF, " "); p; p = strtok(NULL, " ")) { sscanf(p, "%d", &a[i++]); } +} +//һ +template void printn(T x) { + if (x > 9) { printn(x / 10); } + putchar(x % 10 + '0'); +} +//fread +const int BUFSIZE = 1 << 20; +char BUF[BUFSIZE + 1], *S, *T; bool eof; +inline char gc() { + if (S == T) { + S = BUF; T = BUF + fread(BUF, 1, BUFSIZE, stdin); + if (S == T) { eof = true; return EOF; } + } + return *S++; +} +template void ni(T &x) { + char c; bool neg = false; x = 0; + while ((c = gc()) != '-' && !isdigit(c)); + if (eof) { return; } + if (c == '-') { neg = true; c = gc(); } + for (; isdigit(c); c = gc()) { x = x * 10 + c - '0'; } + if (neg) { x = -x; } +} +void nd(double &x) { + char c; bool neg = false; x = 0; + while ((c = gc()) != '-' && !isdigit(c)); + if (eof) { return; } + if (c == '-') { neg = true; c = gc(); } + for (; isdigit(c); c = gc()) { x = x * 10 + c - '0'; } + if (c == '.') { for (double bit = 0.1; isdigit(c = gc()); bit *= 0.1) { x += (c - '0') * bit; } } + if (neg) { x = -x; } +} +void ns(char *s) { + char c; + while (isspace(c = gc())); + if (eof) { return; } + for (; !isspace(c); c = gc()) { *s++ = c; } *s = 0; +} diff --git a/.ACM-Templates/TXTs/高精度.txt b/.ACM-Templates/TXTs/高精度.txt new file mode 100644 index 0000000..91ba31b --- /dev/null +++ b/.ACM-Templates/TXTs/高精度.txt @@ -0,0 +1,195 @@ +//߾ +const int BASE = 1000000000; +const int BASEDIGITS = 9; +struct bint { + vector s; char sign; + bint(): s(), sign(1) {} + bint(const ll &v): s(), sign(v < 0 ? -1 : 1) { + for (ll t = v < 0 ? -v : v; t; t /= BASE) { s.push_back(t % BASE); } + } + bint(const string &v): s(), sign(1) { + int beg = 0; + for (; beg < (int)v.size() && (v[beg] == '-' || v[beg] == '+'); beg++) { + if (v[beg] == '-') { sign = -1; } + } + for (int i = (int)v.size() - 1, x, j; i >= beg; i -= BASEDIGITS) { + for (x = 0, j = max(beg, i - BASEDIGITS + 1); j <= i; x = x * 10 + v[j++] - '0'); + s.push_back(x); + } + trim(); + } + bint &operator=(const bint &v) { sign = v.sign; s = v.s; return *this; } + bint &operator+=(const bint &v) { + if (sign == v.sign) { + for (int i = 0, is = 0, len = max(s.size(), v.s.size()); i < len || is; i++) { + if (i == (int)s.size()) { s.push_back(0); } + s[i] += is + (i < (int)v.s.size() ? v.s[i] : 0); + if ((is = s[i] >= BASE)) { s[i] -= BASE; } + } + return *this; + } else { return *this -= -v; } + } + bint &operator-=(const bint &v) { + if (sign == v.sign) { + if (cmp(v, 0) != -1) { + for (int i = 0, is = 0; i < (int)v.s.size() || is; i++) { + s[i] -= is + (i < (int)v.s.size() ? v.s[i] : 0); + if ((is = s[i] < 0)) { s[i] += BASE; } + } + trim(); return *this; + } else { return *this = -(bint(v) -= *this); } + } else { return *this += -v; } + } + bint &operator*=(const bint &v) { + vector num(s.size() + v.s.size()); + for (int i = 0; i < (int)s.size(); i++) { + for (int j = 0; j < (int)v.s.size(); j++) { + num[i + j] += (ll)s[i] * v.s[j]; + if (num[i + j] >= BASE) { num[i + j + 1] += num[i + j] / BASE; num[i + j] %= BASE; } + } + } + sign *= v.sign; s.resize(num.size()); + for (int i = 0; i < (int)num.size(); i++) { s[i] = num[i]; } + trim(); return *this; + } + bint &operator/=(const bint &v) { return *this = divmod(*this, v).first; } + bint &operator%=(const bint &v) { return *this = divmod(*this, v).second; } + bint operator-()const { bint ret(*this); ret.sign = -sign; return ret; } + bint operator+(const bint &v)const { return bint(*this) += v; } + bint operator-(const bint &v)const { return bint(*this) -= v; } + bint operator*(const bint &v)const { return bint(*this) *= v; } + bint operator/(const bint &v)const { return divmod(*this, v).first; } + bint operator%(const bint &v)const { return divmod(*this, v).second; } + bint operator^(const ll &v)const { + bint ret(1), t(*this); + for (ll b = v; b; b >>= 1) { if (b & 1) { ret *= t; } t *= t; } + return ret; + } + //˳ + friend pair divmod(const bint &a, const bint &b) { + int norm = BASE / (b.s.back() + 1); + bint x = a.abs().mul(norm), y = b.abs().mul(norm), q, r; q.s.resize(x.s.size()); + for (int i = (int)x.s.size() - 1; i >= 0; i--) { + r = r.mul(BASE); r += x.s[i]; + int s1 = r.s.size() <= y.s.size() ? 0 : r.s[y.s.size()]; + int s2 = r.s.size() + 1 <= y.s.size() ? 0 : r.s[y.s.size() - 1]; + int d = ((ll)BASE * s1 + s2) / y.s.back(); + r -= y.mul(d); + while (r.cmp(0, 1) == -1) { r += y; --d; } + q.s[i] = d; + } + q.sign = a.sign * b.sign; q.trim(); r.sign = a.sign; r.trim(); + return make_pair(q, r.div(norm)); + } + bint mul(int v)const { + bint ret(*this); + if (v < 0) { ret.sign = -ret.sign; v = -v; } + for (int i = 0, is = 0; i < (int)ret.s.size() || is; i++) { + if (i == (int)s.size()) { ret.s.push_back(0); } + ll a = ret.s[i] * (ll)v + is; is = a / BASE; ret.s[i] = a % BASE; + } + ret.trim(); return ret; + } + bint div(int v)const { + bint ret(*this); + if (v < 0) { ret.sign = -ret.sign; v = -v; } + for (int i = (int)ret.s.size() - 1, rem = 0; i >= 0; i--) { + ll a = ret.s[i] + rem * (ll)BASE; ret.s[i] = a / v; rem = a % v; + } + ret.trim(); return ret; + } + int mod(int v)const { + if (v < 0) { v = -v; } + int m = 0; + for (int i = (int)s.size() - 1; i >= 0; i--) { m = (s[i] + m * (ll)BASE) % v; } + return m * sign; + } + bool operator<(const bint &v)const { return cmp(v) < 0; } + bool operator>(const bint &v)const { return cmp(v) > 0; } + bool operator<=(const bint &v)const { return cmp(v) <= 0; } + bool operator>=(const bint &v)const { return cmp(v) >= 0; } + bool operator==(const bint &v)const { return cmp(v) == 0; } + bool operator!=(const bint &v)const { return cmp(v) != 0; } + int cmp(const bint &v, bool is = 1)const { + if (is) { if (sign > v.sign) { return 1; } if (sign < v.sign) { return -1; } } + int d = sign > 0 || !is ? 1 : -1; + if (s.size() > v.s.size()) { return d; } + if (s.size() < v.s.size()) { return -d; } + for (int i = (int)s.size() - 1; i >= 0; i--) { + if (s[i] > v.s[i]) { return d; } if (s[i] < v.s[i]) { return -d; } + } + return 0; + } + bint abs()const { bint ret(*this); ret.sign *= ret.sign; return ret; } + void trim() { + while (!s.empty() && !s.back()) { s.pop_back(); } + if (s.empty()) { sign = 1; } + } + void print()const { + if (sign == -1) { putchar('-'); } + printf("%d", s.empty() ? 0 : s.back()); + for (int i = (int)s.size() - 2; i >= 0; i--) { printf("%09d", s[i]); } + } + friend istream &operator>>(istream &in, bint &v) { string s; in >> s; v = s; return in; } + friend ostream &operator<<(ostream &out, const bint &v) { + if (v.sign == -1) { out << '-'; } + out << setfill('0') << (v.s.empty() ? 0 : v.s.back()); + for (int i = (int)v.s.size() - 2; i >= 0; i--) { out << setw(BASEDIGITS) << v.s[i]; } + return out << setfill(' '); + } + string toString()const { + if (s.empty()) { return "0"; } + string ret, x; + if (sign == -1) { ret += '-'; } + for (int o = s[s.size() - 1]; o; o /= 10) { x += o % 10 + '0'; } + for (int i = (int)x.size() - 1; i >= 0; i--) { ret += x[i]; } + for (int i = (int)s.size() - 2; i >= 0; i--) { + x.clear(); + for (int j = 0, p = s[i]; j < BASEDIGITS; j++, p /= 10) { x += p % 10 + '0'; } + for (int j = BASEDIGITS - 1; j >= 0; j--) { ret += x[j]; } + } + return ret; + } + operator bool()const { return s.size() && !(s.size() == 1 && !s[0]); } + //߾ȿ + bint sqrt()const { + bint ret, t(*this); ret.s.resize((t.s.size() + 1) >> 1); + for (int i = (int)ret.s.size() - 1; i >= 0; i--) { + int l = 0, r = BASE - 1, mid = ret.s[i] = (l + r + 1) >> 1; + while (l < r) { + if (comp(ret, mid, i - 1, t)) { r = mid - 1; } + else { l = mid; } + mid = ret.s[i] = (l + r + 1) >> 1; + } + sub(t, ret, mid, i - 1); ret.s[i] += mid; + } + for (int i = 0; i < (int)ret.s.size(); i++) { ret.s[i] >>= 1; } + ret.trim(); return ret; + } + void sub(bint &a, const bint &b, const int &k, const int &d)const { + for (int i = d + 1, l = b.s.size() + d; i <= l; i++) { + ll tmp = a.s[i] - (ll)b.s[i - d - 1] * k; + if (tmp < 0) { a.s[i + 1] += (tmp - BASE + 1) / BASE; a.s[i] = tmp - (tmp - BASE + 1) / BASE * BASE; } + else { a.s[i] = tmp; } + } + for (int i = b.s.size() + d + 1; i < (int)a.s.size() && a.s[i] < 0; i++) { + a.s[i + 1] += (a.s[i] - BASE + 1) / BASE; a.s[i] -= (a.s[i] - BASE + 1) / BASE * BASE; + } + a.trim(); + } + bool comp(const bint &a, const int &c, const int &d, const bint &b)const { + int l = -(BASE << 1); ll t = 0; + if (b.s.size() < a.s.size() + d && c) { return true; } + for (int i = (int)b.s.size() - 1; i > d; i--) { + t = t * BASE + (ll)(i - d - 1 < (int)a.s.size() ? a.s[i - d - 1] : 0) * c - b.s[i]; + if (t > 0) { return true; } + if (t < l) { return false; } + } + for (int i = d - 1; i >= 0; i--) { + t = t * BASE - b.s[i]; + if (t > 0) { return true; } + if (t < l) { return false; } + } + return t > 0; + } +};