From 3f7005ec452e15a115ffad096a6d889587cbd17f Mon Sep 17 00:00:00 2001 From: dtcxzyw <2601110573@qq.com> Date: Mon, 4 Mar 2019 22:49:20 +0800 Subject: [PATCH] 3.4 --- Queue.md | 11 +- Review/Graph/DominatorTree.tex | 1 + Review/NetworkFlows/NetworkFlows.tex | 6 +- Review/NetworkFlows/Tricks.tex | 28 +++ Review/Other/TricksAndIdeas.tex | 5 + Review/Recommendation.tex | 3 + Source/DominatorTree/2597.cpp | 93 ++++++++++ Source/Fractional Programming/LOJ2734.cpp | 154 ++++++++++++++++ Source/K-d Tree/LOJ6016A.cpp | 154 ++++++++++++++++ Source/K-d Tree/LOJ6016B.cpp | 150 ++++++++++++++++ Source/Network Flows/LOJ6014.cpp | 37 ++++ Source/Point-Based Partition/LOJ2065A.cpp | 2 +- Source/Point-Based Partition/LOJ2065B.cpp | 204 +++++++++++++++------- Templates/NegRing.cpp | 10 +- 14 files changed, 786 insertions(+), 72 deletions(-) create mode 100644 Review/NetworkFlows/Tricks.tex create mode 100644 Source/DominatorTree/2597.cpp create mode 100644 Source/Fractional Programming/LOJ2734.cpp create mode 100644 Source/K-d Tree/LOJ6016A.cpp create mode 100644 Source/K-d Tree/LOJ6016B.cpp create mode 100644 Source/Network Flows/LOJ6014.cpp diff --git a/Queue.md b/Queue.md index 734ec57..b69462b 100644 --- a/Queue.md +++ b/Queue.md @@ -15,6 +15,7 @@ - [ ] LOJ#2265. 「CTSC2017」最长上升子序列 - [ ] LOJ#2392. 「JOISC 2017 Day 1」烟花棒 - [ ] LOJ#6500. 「雅礼集训 2018 Day2」操作 +- [ ] [JLOI2011]不重复数字 # 题集 - [ ] PKUWC2018 - [ ] Ynoi2019模拟赛[By OldDriverTree](http://olddrivertree.blog.uoj.ac/blog/4656) @@ -262,6 +263,8 @@ - [ ] UOJ 无限之环 - [ ] CF739E - [ ] 星际竞速 +- [ ] LOJ#6014. 「网络流 24 题」最长 k 可重区间集 +- [ ] LOJ#6008. 「网络流 24 题」餐巾计划(做完补技巧总结) # 分块及按大小分类 - [x] LOJ#6277-6285 # 插头dp @@ -285,7 +288,7 @@ - [ ] LOJ#2341. 「WC2018」即时战略 - [ ] LOJ#2553. 「CTSC2018」暴力写挂 - [x] LOJ#2497. 「PA 2017」Banany -- [ ] LOJ#2065. 「SDOI2016」模式字符串 +- [x] LOJ#2065. 「SDOI2016」模式字符串 - [x] P3727 - [ ] P3920 - [x] P2664 @@ -303,7 +306,7 @@ - [x] CF 613D - [ ] UOJ#87. mx的仙人掌 # kdtree -- [ ] LOJ#6016. 崂山白花蛇草水 +- [x] LOJ#6016. 崂山白花蛇草水 # 计算几何 - [ ] P4586 # 树的直径 @@ -371,7 +374,7 @@ # 置换 - [ ] LOJ#2528. 「ZJOI2018」树 # 支配树 -- [ ] ZJOI 灾难 +- [x] Luogu 2597 ZJOI 灾难 # DSU On Tree - [ ] CF600E - [ ] CF570D @@ -383,7 +386,7 @@ - [ ] CF375D - [ ] CF716E # 分数规划 -- [ ] P3778 [APIO2017]商旅 +- [x] P3778 [APIO2017]商旅 # 贪心 - [ ] LOJ#2734. 「JOISC 2016 Day 2」女装大佬 (FJWC2019上厕所) # 整体二分 diff --git a/Review/Graph/DominatorTree.tex b/Review/Graph/DominatorTree.tex index bcf5b3a..b4bf51c 100644 --- a/Review/Graph/DominatorTree.tex +++ b/Review/Graph/DominatorTree.tex @@ -1,4 +1,5 @@ \section{支配树} +\index{D!DominatorTree} \subsection{定义} 支配树基于某个原点$s$,若$s$到某个点$v$的节点必定经过$u$,则称$u$支配$v$。 起点$s$与自己$v$称为平凡支配点。 diff --git a/Review/NetworkFlows/NetworkFlows.tex b/Review/NetworkFlows/NetworkFlows.tex index 1fb5460..d6e4031 100644 --- a/Review/NetworkFlows/NetworkFlows.tex +++ b/Review/NetworkFlows/NetworkFlows.tex @@ -6,8 +6,4 @@ \chapter{网络流} \input{NetworkFlows/LimitedNetworkFlows} \input{NetworkFlows/Models} \input{NetworkFlows/Gomory-HuTree} -\section{本章注记} -胡伯涛在2007年国家集训队的论文《最小割模型在信息学竞赛中的应用》\cite{MCIOI} -十分经典,我将从这里补充更多的网络流/最小割模型。 -网络流技巧详见\url{https://www.cnblogs.com/zhoushuyu/p/8137534.html}。 -\index{*TODO!补充网络流经典模型与技巧} +\input{NetworkFlows/Tricks} diff --git a/Review/NetworkFlows/Tricks.tex b/Review/NetworkFlows/Tricks.tex new file mode 100644 index 0000000..07afa04 --- /dev/null +++ b/Review/NetworkFlows/Tricks.tex @@ -0,0 +1,28 @@ +\section{技巧总结} +\subsection{最大流} +\begin{itemize} + \item 若一个点只能被经过有限次,将其拆为入点和出点,入点到出点连流量为 + 经过次数限制的边。 + \item 树形最大流可以贪心解决。 +\end{itemize} +\subsection{最小割} +\begin{itemize} + \item 最大化收益可以理解为已经拿到所有收益,最小化损失。然后将其转化为最小割解决。 + \item 使用$+\infty$边描述依赖关系,可以保证这条边不出现在最小割中。 + \item 用$S,T$与点的连边来表示点的权。 +\end{itemize} +\subsection{费用流} +\begin{itemize} + \item 要求费用最小且边数最小:类比进制的思想,实际费用乘以一个大于总边数的因子,再加上 + 1作为该边边权。 + \item 若已知走一条边之前必定已经走完了另外几条边,则考虑动态加边。 + \item 对于层数较少,结构简单的图,考虑使用其它数据结构贪心模拟费用流。 + \item (待验证)判断一条边是否一定被选:在残量网络上跑SPFA,若距离差不等于边权则必选。 + \item 餐巾计划问题: +\end{itemize} + +上述内容参考了胡伯涛的2007年国家集训队论文《最小割模型在信息学竞赛中的应用》 +\cite{MCIOI}和租酥雨的博客\footnote{ + 网络流总结\\ + \url{https://www.cnblogs.com/zhoushuyu/p/8137534.html} +}。 diff --git a/Review/Other/TricksAndIdeas.tex b/Review/Other/TricksAndIdeas.tex index 887bf8b..43e7fe4 100644 --- a/Review/Other/TricksAndIdeas.tex +++ b/Review/Other/TricksAndIdeas.tex @@ -360,6 +360,11 @@ \subsection{启发式分治} 「随笔」一种基于启发式思想的分治策略——启发式分裂 \url{https://blog.csdn.net/DSL\_HN\_2002/article/details/81193576} }。 +\subsection{分段打表} +需求:少量大规模单点查询,查询上界已知,支持快速转移。比如求$1e9$范围内的模意义阶乘。 + +可以写一个打表程序,每隔$1e5$输出一个点,然后将其导入源程序,查询时寻找最近的点, +从该点开始转移。 \subsection{注意事项/常见转化/思想} \begin{itemize} \item 边读入边处理时不要跳出循环,若要跳出循环则需继续读入以跳过冗余数据。 diff --git a/Review/Recommendation.tex b/Review/Recommendation.tex index dc5f7ab..785cf4e 100644 --- a/Review/Recommendation.tex +++ b/Review/Recommendation.tex @@ -28,6 +28,7 @@ \section{好用的网站/工具} \item BZOJ离线题库(BZOJCH)[By 阮行止] \\\url{http://ruanx.pw/bzojch/index.html} \item BZOJ题号查找器(BZOJNO)[By 阮行止] \url{http://ruanx.pw/bzojch/bzojno.html} + \item 马同学高等数学 \url{https://www.matongxue.com/} \end{itemize} \section{优秀资料} \begin{itemize} @@ -36,6 +37,8 @@ \section{优秀资料} \item OI-Wiki \url{https://github.com/24OI/OI-wiki/} \item 知乎上OI相关文章 \url{https://www.zhihu.com/collection/213577780} \item 演算法筆記 江任捷\\\url{http://www.csie.ntnu.edu.tw/\~u91029/index.html} + \item 一份不太简短的\LaTeX{}$2_{\varepsilon}$介绍\\ + \url{https://github.com/CTeX-org/lshort-cn/} \end{itemize} \section{经典书籍} \begin{itemize} diff --git a/Source/DominatorTree/2597.cpp b/Source/DominatorTree/2597.cpp new file mode 100644 index 0000000..6587f92 --- /dev/null +++ b/Source/DominatorTree/2597.cpp @@ -0,0 +1,93 @@ +#include +#include +int read() { + int res = 0, c; + do + c = getchar(); + while(c < '0' || c > '9'); + while('0' <= c && c <= '9') { + res = res * 10 + c - '0'; + c = getchar(); + } + return res; +} +const int size = 70000; +template +struct G { + struct Edge { + int to, nxt; + } E[esiz]; + int last[size], cnt; + G() : cnt(0) {} + void addEdge(int u, int v) { + ++cnt; + E[cnt].to = v, E[cnt].nxt = last[u]; + last[u] = cnt; + } +}; +G A; +G B; +int in[size], q[size], d[size], p[size][16], siz[size]; +void DFS(int u) { + siz[u] = 1; + for(int i = B.last[u]; i; i = B.E[i].nxt) { + int v = B.E[i].to; + if(v != p[u][0]) { + DFS(v); + siz[u] += siz[v]; + } + } +} +int getLCA(int u, int v) { + if(u == 0 || v == 0) + return u | v; + if(d[u] < d[v]) + std::swap(u, v); + int delta = d[u] - d[v]; + for(int i = 0; i < 16; ++i) + if(delta & (1 << i)) + u = p[u][i]; + if(u == v) + return u; + for(int i = 15; i >= 0; --i) + if(p[u][i] != p[v][i]) + u = p[u][i], v = p[v][i]; + return p[u][0]; +} +int main() { + int n = read(); + for(int i = 1; i <= n; ++i) { + int k = read(); + while(k) { + ++in[i]; + A.addEdge(k, i); + k = read(); + } + } + int qcnt = 0, rt = n + 1; + for(int i = 1; i <= n; ++i) + if(!in[i]) { + B.addEdge(rt, i); + p[i][0] = rt; + q[++qcnt] = i; + d[i] = 1; + } + for(int i = 1; i <= qcnt; ++i) { + int u = q[i]; + for(int j = A.last[u]; j; j = A.E[j].nxt) { + int v = A.E[j].to; + p[v][0] = getLCA(p[v][0], u); + if(--in[v] == 0) { + B.addEdge(p[v][0], v); + d[v] = d[p[v][0]] + 1; + for(int k = 1; k < 16; ++k) + p[v][k] = p[p[v][k - 1]][k - 1]; + q[++qcnt] = v; + } + } + } + DFS(rt); + for(int i = 1; i <= n; ++i) + printf("%d\n", siz[i] - 1); + return 0; +} diff --git a/Source/Fractional Programming/LOJ2734.cpp b/Source/Fractional Programming/LOJ2734.cpp new file mode 100644 index 0000000..f2cf9bf --- /dev/null +++ b/Source/Fractional Programming/LOJ2734.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +namespace IO { + void init() { + assert(setvbuf(stdin, 0, _IONBF, 0) == 0); + assert(setvbuf(stdout, 0, _IONBF, 0) == 0); + } + const int size = 1 << 21; + char in[size]; + char getc() { + static char *S = in, *T = in; + if(S == T) + S = in, T = in + fread(in, 1, size, stdin); + return S == T ? EOF : *S++; + } +} +int read() { + int res = 0, c; + bool flag = false; + do { + c = IO::getc(); + flag |= c == '-'; + } while(c < '0' || c > '9'); + while('0' <= c && c <= '9') { + res = res * 10 + c - '0'; + c = IO::getc(); + } + return flag ? -res : res; +} +const int size = 105, maxk = 1005, inf = 0x3f3f3f3f; +typedef double FT; +const FT eps = 1e-2; +struct Edge { + int to, nxt; + FT w; +} E[size * size]; +int last[size], cnt; +void addEdge(int u, int v, FT w) { + ++cnt; + E[cnt].to = v, E[cnt].nxt = last[u], E[cnt].w = w; + last[u] = cnt; +} +FT dis[size]; +bool vis[size]; +jmp_buf buf; +bool pre(int u) { + FT cd = dis[u]; + vis[u] = true; + bool res = false; + for(int i = last[u]; i; i = E[i].nxt) { + int v = E[i].to; + FT dv = cd + E[i].w; + if(dv < dis[v]) { + if(vis[v]) + longjmp(buf, 1); + dis[v] = dv; + pre(v); + res = true; + break; + } + } + vis[u] = false; + return res; +} +void DFS(int u, int d) { + if(d == 0) + return; + FT cd = dis[u]; + vis[u] = true; + for(int i = last[u]; i; i = E[i].nxt) { + int v = E[i].to; + FT dv = cd + E[i].w; + if(dv < dis[v]) { + if(vis[v]) + longjmp(buf, 1); + dis[v] = dv; + DFS(v, d - 1); + } + } + vis[u] = false; +} +int link[size][size], off[size][size]; +bool check(int n, int K, FT x) { + cnt = 0; + memset(last + 1, 0, sizeof(int) * n); + for(int i = 1; i <= n; ++i) + for(int j = 1; j <= n; ++j) { + if(off[i][j] != inf && link[i][j] != inf) + addEdge(i, j, + off[i][j] + link[i][j] * x); + } + memset(vis + 1, 0, sizeof(bool) * n); + memset(dis + 1, 0, sizeof(double) * n); + if(setjmp(buf)) + return true; + else { + for(int i = 1; i <= n; ++i) + while(pre(i)) + ; + int end = 2 * n; + for(int k = 1; k < end; k <<= 1) + for(int i = 1; i <= n; ++i) + DFS(i, k); + return false; + } +} +int b[size][maxk], s[size][maxk]; +int main() { + IO::init(); + int n = read(); + int m = read(); + int K = read(); + for(int i = 1; i <= n; ++i) + for(int j = 1; j <= K; ++j) { + b[i][j] = read(); + s[i][j] = read(); + } + for(int i = 1; i <= n; ++i) + for(int j = 1; j <= n; ++j) { + int& mind = off[i][j]; + mind = inf; + if(i == j) + continue; + for(int k = 1; k <= K; ++k) + if(b[i][k] != -1 && s[j][k] != -1) + mind = std::min(mind, + b[i][k] - s[j][k]); + } + memset(link, 0x3f, sizeof(link)); + for(int i = 1; i <= m; ++i) { + int u = read(); + int v = read(); + int t = read(); + link[u][v] = std::min(link[u][v], t); + } + for(int k = 1; k <= n; ++k) + for(int i = 1; i <= n; ++i) + if(link[i][k] != inf) + for(int j = 1; j <= n; ++j) + link[i][j] = std::min( + link[i][j], + link[i][k] + link[k][j]); + FT l = 100.0, r = 350.0; + while(floor(r + eps) - floor(l + eps) >= eps) { + FT m = (l + r) / 2.0; + (check(n, K, m) ? l : r) = m; + } + printf("%.0lf\n", floor(r + eps)); + return 0; +} diff --git a/Source/K-d Tree/LOJ6016A.cpp b/Source/K-d Tree/LOJ6016A.cpp new file mode 100644 index 0000000..27de68a --- /dev/null +++ b/Source/K-d Tree/LOJ6016A.cpp @@ -0,0 +1,154 @@ +#include +#include +int read() { + int res = 0, c; + do + c = getchar(); + while(c < '0' || c > '9'); + while('0' <= c && c <= '9') { + res = res * 10 + c - '0'; + c = getchar(); + } + return res; +} +const int size = 100005; +struct Point { + int x, y, z; + Point() {} + Point(int x, int y, int z) : x(x), y(y), z(z) {} +} P[size]; +typedef const Point& CRef; +bool cmpX(CRef a, CRef b) { + return a.x < b.x; +} +bool cmpY(CRef a, CRef b) { + return a.y < b.y; +} +bool cmpZ(CRef a, CRef b) { + return a.z < b.z; +} +typedef bool (*cmpFunc)(CRef, CRef); +cmpFunc LUT[3] = { cmpZ, cmpX, cmpY }; +void updateMin(Point& a, CRef b) { + a.x = std::min(a.x, b.x); + a.y = std::min(a.y, b.y); + a.z = std::min(a.z, b.z); +} +void updateMax(Point& a, CRef b) { + a.x = std::max(a.x, b.x); + a.y = std::max(a.y, b.y); + a.z = std::max(a.z, b.z); +} +struct Node { + Point p, minP, maxP; + int siz, c[2]; + void update(Node& rhs) { + updateMin(minP, rhs.minP); + updateMax(maxP, rhs.maxP); + } +} T[size]; +#define ls T[u].c[0] +#define rs T[u].c[1] +int tcnt = 0; +int build(int l, int r, int axis) { + if(l > r) + return 0; + int m = (l + r) >> 1; + std::nth_element(P + l, P + m, P + r + 1, + LUT[axis]); + axis = (axis + 1) % 3; + int u = ++tcnt; + T[u].p = T[u].minP = T[u].maxP = P[m]; + if((ls = build(l, m - 1, axis))) + T[u].update(T[ls]); + if((rs = build(m + 1, r, axis))) + T[u].update(T[rs]); + T[u].siz = 1 + T[ls].siz + T[rs].siz; + return u; +} +void insert(int& u, CRef p, int axis) { + if(u) { + ++T[u].siz; + updateMin(T[u].minP, p); + updateMax(T[u].maxP, p); + bool cp = (LUT[axis])(T[u].p, p); + insert(T[u].c[cp], p, (axis + 1) % 3); + } else { + u = ++tcnt; + T[u].p = T[u].minP = T[u].maxP = p; + T[u].siz = 1; + ls = rs = 0; + } +} +int ans, x1, x2, y1, y2, val; +void queryImpl(int u) { + if(u == 0 || ans < 0) + return; + if(T[u].minP.x > x2 || T[u].maxP.x < x1 || + T[u].minP.y > y2 || T[u].maxP.y < y1 || + T[u].maxP.z <= val) + return; + if(x1 <= T[u].minP.x && T[u].maxP.x <= x2 && + y1 <= T[u].minP.y && T[u].maxP.y <= y2 && + T[u].minP.z > val) { + ans -= T[u].siz; + return; + } + if(x1 <= T[u].p.x && T[u].p.x <= x2 && + y1 <= T[u].p.y && T[u].p.y <= y2 && + T[u].p.z > val) + --ans; + queryImpl(ls); + queryImpl(rs); +} +int query(int rt, int k, int l, int r) { + ans = k, val = 0; + queryImpl(rt); + if(ans > 0) + return 0; + int res = 0; + while(l <= r) { + val = (l + r) >> 1; + ans = k - 1; + queryImpl(rt); + if(ans < 0) + l = val + 1; + else + res = val, r = val - 1; + } + return res; +} +int main() { + int n = read(); + int q = read(); + int minv = 1 << 30, maxv = 0, rt = 0, cnt = 0, + lastAns = 0; + for(int i = 1; i <= q; ++i) { + if(read() == 1) { + int x = read() ^ lastAns; + int y = read() ^ lastAns; + int z = read() ^ lastAns; + minv = std::min(minv, z); + maxv = std::max(maxv, z); + P[++cnt] = Point(x, y, z); + insert(rt, P[cnt], 0); + } else { + x1 = read() ^ lastAns; + y1 = read() ^ lastAns; + x2 = read() ^ lastAns; + y2 = read() ^ lastAns; + int k = read() ^ lastAns; + int res = query(rt, k, minv, maxv); + if(res) + printf("%d\n", res); + else + puts("NAIVE!ORZzyz."); + lastAns = res; + } + if(i % 5000 == 0) { + tcnt = 0; + rt = build(1, cnt, 0); + } + } + return 0; +} diff --git a/Source/K-d Tree/LOJ6016B.cpp b/Source/K-d Tree/LOJ6016B.cpp new file mode 100644 index 0000000..879d242 --- /dev/null +++ b/Source/K-d Tree/LOJ6016B.cpp @@ -0,0 +1,150 @@ +#include +#include +int read() { + int res = 0, c; + do + c = getchar(); + while(c < '0' || c > '9'); + while('0' <= c && c <= '9') { + res = res * 10 + c - '0'; + c = getchar(); + } + return res; +} +const int size = 100005; +struct Point { + int x, y, z; + Point() {} + Point(int x, int y, int z) : x(x), y(y), z(z) {} +} P[size]; +typedef const Point& CRef; +bool cmpX(CRef a, CRef b) { + return a.x < b.x; +} +bool cmpY(CRef a, CRef b) { + return a.y < b.y; +} +bool cmpZ(CRef a, CRef b) { + return a.z < b.z; +} +typedef bool (*cmpFunc)(CRef, CRef); +cmpFunc LUT[3] = { cmpZ, cmpX, cmpY }; +void updateMin(Point& a, CRef b) { + a.x = std::min(a.x, b.x); + a.y = std::min(a.y, b.y); + a.z = std::min(a.z, b.z); +} +void updateMax(Point& a, CRef b) { + a.x = std::max(a.x, b.x); + a.y = std::max(a.y, b.y); + a.z = std::max(a.z, b.z); +} +struct Node { + Point p, minP, maxP; + int siz, c[2]; + void update(Node& rhs) { + updateMin(minP, rhs.minP); + updateMax(maxP, rhs.maxP); + } +} T[size]; +#define ls T[u].c[0] +#define rs T[u].c[1] +int tcnt = 0; +int build(int l, int r, int axis) { + if(l > r) + return 0; + int m = (l + r) >> 1; + std::nth_element(P + l, P + m, P + r + 1, + LUT[axis]); + axis = (axis + 1) % 3; + int u = ++tcnt; + T[u].p = T[u].minP = T[u].maxP = P[m]; + if((ls = build(l, m - 1, axis))) + T[u].update(T[ls]); + if((rs = build(m + 1, r, axis))) + T[u].update(T[rs]); + T[u].siz = 1 + T[ls].siz + T[rs].siz; + return u; +} +void insert(int& u, CRef p, int axis) { + if(u) { + ++T[u].siz; + updateMin(T[u].minP, p); + updateMax(T[u].maxP, p); + bool cp = (LUT[axis])(T[u].p, p); + insert(T[u].c[cp], p, (axis + 1) % 3); + } else { + u = ++tcnt; + T[u].p = T[u].minP = T[u].maxP = p; + T[u].siz = 1; + ls = rs = 0; + } +} +int ans, x1, x2, y1, y2, z1, z2; +void queryImpl(int u) { + if(u == 0 || ans < 0) + return; + if(T[u].minP.x > x2 || T[u].maxP.x < x1 || + T[u].minP.y > y2 || T[u].maxP.y < y1 || + T[u].minP.z > z2 || T[u].maxP.z < z1) + return; + if(x1 <= T[u].minP.x && T[u].maxP.x <= x2 && + y1 <= T[u].minP.y && T[u].maxP.y <= y2 && + z1 <= T[u].minP.z && T[u].maxP.z <= z2) { + ans -= T[u].siz; + return; + } + if(x1 <= T[u].p.x && T[u].p.x <= x2 && + y1 <= T[u].p.y && T[u].p.y <= y2 && + z1 <= T[u].p.z && T[u].p.z <= z2) + --ans; + queryImpl(ls); + queryImpl(rs); +} +int query(int rt, int k) { + --k; + int res = (1 << 30) - 1, sum = 0; + for(int i = 29; i >= 0; --i) { + int cur = res ^ (1 << i); + z1 = cur + 1, z2 = res; + int rem = k - sum; + ans = rem; + queryImpl(rt); + if(ans >= 0) { + res = cur; + sum += rem - ans; + } + } + return res; +} +int main() { + int n = read(); + int q = read(); + int rt = 0, cnt = 0, lastAns = 0; + for(int i = 1; i <= q; ++i) { + if(read() == 1) { + int x = read() ^ lastAns; + int y = read() ^ lastAns; + int z = read() ^ lastAns; + P[++cnt] = Point(x, y, z); + insert(rt, P[cnt], 0); + } else { + x1 = read() ^ lastAns; + y1 = read() ^ lastAns; + x2 = read() ^ lastAns; + y2 = read() ^ lastAns; + int k = read() ^ lastAns; + int res = query(rt, k); + if(res) + printf("%d\n", res); + else + puts("NAIVE!ORZzyz."); + lastAns = res; + } + if(i % 5000 == 0) { + tcnt = 0; + rt = build(1, cnt, 0); + } + } + return 0; +} diff --git a/Source/Network Flows/LOJ6014.cpp b/Source/Network Flows/LOJ6014.cpp new file mode 100644 index 0000000..ee47bef --- /dev/null +++ b/Source/Network Flows/LOJ6014.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +const int size = 1010; +struct Edge { + int to, rev, f, w; + Edge(int to, int rev, int f, int w) + : to(to), rev(rev), f(f), w(w) {} +}; +std::vector G[size]; +void addEdge(int u, int v, int f, int w) { + int usiz = G[u].size(), vsiz = G[v].size(); + G[u].push_back(Edge(v, vsiz, f, w)); + G[v].push_back(Edge(u, usiz, 0, -w)); +} +int dis[size], S, T; +void BFS(int n) {} +bool flag[size]; +void DFS(int u, int f) {} +int MCMF(int n) {} +int L[size], R[size], P[size]; +int main() { + int n, k; + scanf("%d%d", &n, &k); + int pcnt = 0; + for(int i = 1; i <= n; ++i) { + scanf("%d%d", &L[i], &R[i]); + if(L[i] > R[i]) + std::swap(L[i], R[i]); + P[++pcnt] = L[i]; + P[++pcnt] = R[i]; + } + std::sort(P + 1, P + pcnt + 1); + pcnt = std::unique(P + 1, P + pcnt + 1) - (P + 1); + + return 0; +} diff --git a/Source/Point-Based Partition/LOJ2065A.cpp b/Source/Point-Based Partition/LOJ2065A.cpp index c0bc709..7c951bc 100644 --- a/Source/Point-Based Partition/LOJ2065A.cpp +++ b/Source/Point-Based Partition/LOJ2065A.cpp @@ -12,7 +12,7 @@ int read() { } return res; } -const int size = 1000005; +const int size = 100005; struct Edge { int to, nxt; } E[size * 2]; diff --git a/Source/Point-Based Partition/LOJ2065B.cpp b/Source/Point-Based Partition/LOJ2065B.cpp index fe168f7..16ffcad 100644 --- a/Source/Point-Based Partition/LOJ2065B.cpp +++ b/Source/Point-Based Partition/LOJ2065B.cpp @@ -1,19 +1,33 @@ -// TOFIX #include +#include #include #include +namespace IO { + void init() { + assert(setvbuf(stdin, 0, _IONBF, 0) == 0); + assert(setvbuf(stdout, 0, _IONBF, 0) == 0); + } + const int size = 1 << 24; + char in[size]; + char getc() { + static char *S = in, *T = in; + if(S == T) + S = in, T = in + fread(in, 1, size, stdin); + return S == T ? EOF : *S++; + } +} int read() { int res = 0, c; do - c = getchar(); + c = IO::getc(); while(c < '0' || c > '9'); while('0' <= c && c <= '9') { res = res * 10 + c - '0'; - c = getchar(); + c = IO::getc(); } return res; } -const int size = 1000005; +const int size = 100005; struct Edge { int to, nxt; } E[size * 2]; @@ -45,32 +59,45 @@ int getRoot(int u, int usiz) { getRootImpl(u, 0); return crt; } -typedef unsigned long long Int64; +typedef long long Int64; #define asInt64 static_cast -const int modu = 2000003, modv = 1999993, fac = 131; +const int modu = 2003, modv = 1999, fac = 131; +struct HashValue { + int HA, HB; + HashValue() {} + explicit HashValue(int ch) + : HA(ch % modu), HB(ch % modv) {} + bool operator==(HashValue& rhs) const { + return HA == rhs.HA && HB == rhs.HB; + } + HashValue extend(int ch) const { + HashValue res; + res.HA = (HA * fac + ch) % modu; + res.HB = (HB * fac + ch) % modv; + return res; + } +}; struct HashTable { - Int64 A[modu]; + HashValue A[modu]; void reset() { memset(A, 0, sizeof(A)); } - int find(Int64 val) { - int ha = val % modu, hb = 1 + val % modv, - cur = ha; + int find(HashValue val) { + int ha = val.HA, hb = 1 + val.HB, cur = ha; while(true) { if(A[cur] == val) return cur; - if(A[cur] == 0) + if(A[cur].HA == 0 && A[cur].HB == 0) return -1; cur += hb; if(cur >= modu) cur -= modu; } } - int insert(Int64 val) { - int ha = val % modu, hb = 1 + val % modv, - cur = ha; + int insert(HashValue val) { + int ha = val.HA, hb = 1 + val.HB, cur = ha; while(true) { - if(A[cur] == 0) { + if(A[cur].HA == 0 && A[cur].HB == 0) { A[cur] = val; return cur; } @@ -81,7 +108,7 @@ struct HashTable { } } HA, HB, HC, HD; Int64 ans; -int m; +int m, end; char S[size], P[size]; void reset(int n) { cnt = 0; @@ -93,25 +120,38 @@ void reset(int n) { HD.reset(); } int posA[modu], posB[modu]; -Int64 remapA[modu], remapB[modu]; +HashValue remapA[modu], remapB[modu]; int A[size], LA, B[size], LB, C[size], LC, D[size], LD; -void DFS(int u, int p, Int64 valA, Int64 valB) { +void DFSA(int u, int p, int len, HashValue val) { { - int id = HB.find(valA); - if(id != -1) - valA = remapA[id]; - id = HA.find(valA); + int id = HB.find(val); + if(id != -1) { + val = remapA[id]; + len -= m; + } else if(len > end) + return; + id = HA.find(val); if(id != -1) { id = posA[id]; ++C[id]; LC = std::max(LC, id); } } + for(int i = last[u]; i; i = E[i].nxt) { + int v = E[i].to; + if(v != p && !vis[v]) + DFSA(v, u, len + 1, val.extend(S[v])); + } +} +void DFSB(int u, int p, int len, HashValue val) { { - int id = HD.find(valB); - if(id != -1) - valB = remapB[id]; - id = HC.find(valB); + int id = HD.find(val); + if(id != -1) { + val = remapB[id]; + len -= m; + } else if(len > end) + return; + id = HC.find(val); if(id != -1) { id = posB[id]; ++D[id]; @@ -121,25 +161,29 @@ void DFS(int u, int p, Int64 valA, Int64 valB) { for(int i = last[u]; i; i = E[i].nxt) { int v = E[i].to; if(v != p && !vis[v]) - DFS(v, u, valA * fac + S[v], - valB * fac + S[v]); + DFSB(v, u, len + 1, val.extend(S[v])); } } +bool flag = false; void solve(int u) { LA = LB = 0; - B[0] = 1; - if(S[u] == P[m]) - A[1] = 1; for(int i = last[u]; i; i = E[i].nxt) { int v = E[i].to; if(!vis[v]) { LC = LD = 0; - DFS(v, u, asInt64(S[u]) * fac + S[v], - S[v]); - for(int j = 1; j <= LC; ++j) - ans += asInt64(C[j]) * B[m - j]; - for(int j = 1; j <= LD; ++j) - ans += asInt64(D[j]) * A[m - j]; + DFSA(v, u, 2, + HashValue(S[u]).extend(S[v])); + DFSB(v, u, 1, HashValue(S[v])); + for(int j = 1; j <= LC; ++j) { + int rev = m == j ? m : m - j; + ans += asInt64(C[j]) * B[rev]; + } + if(flag) { + for(int j = 1; j <= LD; ++j) { + int rev = m == j ? m : m - j; + ans += asInt64(D[j]) * A[rev]; + } + } for(int j = 1; j <= LC; ++j) { A[j] += C[j]; C[j] = 0; @@ -152,10 +196,12 @@ void solve(int u) { LB = std::max(LB, LD); } } + if(flag) + ans += A[m]; + if(S[u] == P[m]) + ans += B[m - 1]; memset(A + 1, 0, sizeof(int) * LA); memset(B + 1, 0, sizeof(int) * LB); - printf("%d %llu\n", u, ans); - throw; } void divide(int u) { vis[u] = true; @@ -168,52 +214,92 @@ void divide(int u) { } } } -Int64 tmp[size]; +HashValue tmp[size]; Int64 foo() { int n = read(); reset(n); m = read(); - scanf("%s", S + 1); + end = 2 * m; + for(int i = 1; i <= n; ++i) { + int c; + do + c = IO::getc(); + while(c < 'A' || c > 'Z'); + S[i] = c; + } for(int i = 1; i < n; ++i) { int u = read(); int v = read(); addEdge(u, v); addEdge(v, u); } - scanf("%s", P + 1); + for(int i = 1; i <= m; ++i) { + int c; + do + c = IO::getc(); + while(c < 'A' || c > 'Z'); + P[i] = c; + } + flag = false; + for(int i = 1; i <= m; ++i) + if(P[i] != P[m + 1 - i]) { + flag = true; + break; + } { - Int64 base = 1, cur = 0; + int bu = 1, vu = 0, bv = 1, vv = 0; for(int i = m; i >= 1; --i) { - cur += base * P[i]; - base *= fac; - posA[HA.insert(cur)] = m + 1 - i; - tmp[i] = cur; + vu = (vu + bu * P[i]) % modu; + bu = bu * fac % modu; + vv = (vv + bv * P[i]) % modv; + bv = bv * fac % modv; + HashValue val; + val.HA = vu; + val.HB = vv; + posA[HA.insert(val)] = m + 1 - i; + tmp[i] = val; } for(int i = m; i >= 1; --i) { - cur += base * P[i]; - base *= fac; - remapA[HB.insert(cur)] = tmp[i]; + vu = (vu + bu * P[i]) % modu; + bu = bu * fac % modu; + vv = (vv + bv * P[i]) % modv; + bv = bv * fac % modv; + HashValue val; + val.HA = vu; + val.HB = vv; + remapA[HB.insert(val)] = tmp[i]; } } { - Int64 base = 1, cur = 0; + int bu = 1, vu = 0, bv = 1, vv = 0; for(int i = 1; i <= m; ++i) { - cur += base * P[i]; - base *= fac; - posB[HC.insert(cur)] = i; - tmp[i] = cur; + vu = (vu + bu * P[i]) % modu; + bu = bu * fac % modu; + vv = (vv + bv * P[i]) % modv; + bv = bv * fac % modv; + HashValue val; + val.HA = vu; + val.HB = vv; + posB[HC.insert(val)] = i; + tmp[i] = val; } for(int i = 1; i <= m; ++i) { - cur += base * P[i]; - base *= fac; - remapB[HD.insert(cur)] = tmp[i]; + vu = (vu + bu * P[i]) % modu; + bu = bu * fac % modu; + vv = (vv + bv * P[i]) % modv; + bv = bv * fac % modv; + HashValue val; + val.HA = vu; + val.HB = vv; + remapB[HD.insert(val)] = tmp[i]; } } ans = 0; divide(getRoot(1, n)); - return ans; + return flag ? ans : ans * 2; } int main() { + IO::init(); int t = read(); for(int i = 0; i < t; ++i) printf("%llu\n", foo()); diff --git a/Templates/NegRing.cpp b/Templates/NegRing.cpp index 4882827..bf943fc 100644 --- a/Templates/NegRing.cpp +++ b/Templates/NegRing.cpp @@ -27,9 +27,10 @@ void addEdge(int u, int v, int w) { int dis[maxn], n; bool flag[maxn]; jmp_buf buf; -void pre(int u) { +bool pre(int u) { int cd = dis[u]; flag[u] = true; + bool res = false; for(int i = last[u]; i; i = E[i].nxt) { int v = E[i].to, nd = cd + E[i].w; if(dis[v] > nd) { @@ -37,10 +38,12 @@ void pre(int u) { longjmp(buf, 1); dis[v] = nd; pre(v); + res = true; + break; } - break; } flag[u] = false; + return res; } void DFS(int u, int d) { if(d) { @@ -88,7 +91,8 @@ bool foo() { case 0: { for(int i = 1; i <= n; ++i) if(vis[i]) - pre(i); + while(pre(i)) + ; for(int k = 1; k <= n * 2; k <<= 1) for(int i = 1; i <= n; ++i) if(vis[i])