@jason-fan
2023-07-30T13:51:11.000000Z
字数 112222
阅读 68
jasonfan 的算法模板。
/*
Dancing Links X : 舞蹈链优化 X 算法
干啥的 --> 求解精准覆盖问题
Oi-wiki(Dancing Links) --> https://oi-wiki.org/search/dlx/
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
int n, m, a[N][N];
namespace DLX { // 舞蹈链,这实际上是个双十字循环链表
const int N = 10010;
int tot, fir[N], siz[N];
int L[N], R[N], U[N], D[N];
int col[N], row[N], st[N], ans;
void Remove(int c) {
L[R[c]] = L[c], R[L[c]] = R[c];
for (int i = D[c]; i != c; i = D[i]) for (int j = R[i]; j != i;
j = R[j]) U[D[j]] = U[j], D[U[j]] = D[j], --siz[col[j]];
}
void Recover(int c) {
for (int i = U[c]; i != c; i = U[i]) for (int j = L[i]; j != i;
j = L[j]) U[D[j]] = D[U[j]] = j, ++siz[col[j]];
L[R[c]] = R[L[c]] = c;
}
void Insert(int r, int c) {
++tot; row[tot] = r; col[tot] = c; ++siz[c];
U[tot] = c; D[tot] = D[c]; U[D[c]] = tot; D[c] = tot;
if (!fir[r])
fir[r] = L[tot] = R[tot] = tot;
else {
L[tot] = fir[r]; R[tot] = R[fir[r]];
L[R[fir[r]]] = tot; R[fir[r]] = tot;
}
}
void Build(int r, int c) {
for (int i = 0; i <= c; ++i) L[i] = i - 1, R[i] = i + 1, U[i] = D[i] = i;
L[0] = c, R[c] = 0; tot = c;
memset(fir, 0, sizeof(fir));
memset(siz, 0, sizeof(siz));
}
bool Dance(int dep) {
int c = R[0];
if (!R[0]) { ans = dep; return 1;}
for (int i = R[0]; i != 0; i = R[i]) if (siz[i] < siz[c]) c = i;
Remove(c);
for (int i = D[c]; i != c; i = D[i]) {
st[dep] = row[i];
for (int j = R[i]; j != i; j = R[j]) Remove(col[j]);
if (Dance(dep + 1)) return 1;
for (int j = L[i]; j != i; j = L[j]) Recover(col[j]);
}
Recover(c);
return 0;
}
}
void solve() {
using namespace DLX;
Build(n, m);
for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (a[i][j] == 1) Insert(i, j);
bool fg = Dance(1);
if (!fg) puts("No Solution!");
else {
for (int i = 1; i < ans; ++i) printf("%d ", st[i]);
printf("\n");
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) scanf("%d", &a[i][j]);
solve();
}
// 树状数组(Fenwick Tree) 区间加减,区间求和
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
struct fenwick {
ll s1[N], s2[N]; int n;
void _add(int p, int v) {for (int x = p; x <= n; x += x & -x) s1[x] += v, s2[x] += (ll)v * p;}
ll ask(int p) {ll r = 0; for (int x = p; x > 0; x -= x & -x) r += (ll)(p + 1) * s1[x] - s2[x]; return r;}
ll query(int l, int r) {return ask(r) - ask(l - 1);}
void modify(int l, int r, int v) {_add(l, v); _add(r + 1, -v);}
void init(int n, int a[]) {
fenwick::n = n;
for (int i = 1, j; i <= n; ++i) {
s1[i] += a[i] - a[i - 1]; s2[i] += (ll)(a[i] - a[i - 1]) * i;
j = i + (i & -i);
if (j <= n) s1[j] += s1[i], s2[j] += s2[i];
}
}
} T;
int n, q, a[N];
int main() {
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
T.init(n, a);
while (q--) {
int op, l, r, x;
scanf("%d%d%d", &op, &l, &r);
if (op == 1) {
scanf("%d", &x);
T.modify(l, r, x);
} else
printf("%lld\n", T.query(l, r));
}
return 0;
}
// fhq - treap 简易模板
#include <bits/stdc++.h>
#define ls(p) t[p].l
#define rs(p) t[p].r
#define mid ((l+r)>>1)
using namespace std;
const int N = 100010;
mt19937 rd(random_device{}()); // random maker
struct node {
int l, r, siz, rnd, val, tag; /* other data/tags */
} t[N]; int tot, root;
/* ---------- for recycle nodes ------------
int cyc[N],cyccnt;
inline void delnode(int p) {cyc[++cyccnt]=p;}
inline void newnode(int val) {
int id=(cyccnt>0)?cyc[cyccnt--]:++tot;
t[id]={0,0,1,(int)(rd()),val}; return id;
}
*/
inline int newnode(int val) { t[++tot] = {0, 0, 1, (int)(rd()), val}; return tot;} // create a new node
inline void updata(int p) {t[p].siz = t[ls(p)].siz + t[rs(p)].siz + 1; /* pushup other datas */ }
inline void pushtag(int p, int vl) { /* tag to push */ }
inline void pushdown(int p) {
if (t[p].tag != std_tag) {
if (ls(p)) pushtag(ls(p), t[p].tag);
if (rs(p)) pushtag(rs(p), t[p].tag);
t[p].tag = std_tag;
}
}
int merge(int p, int q) {
if (!p || !q) return p + q;
if (t[p].rnd < t[q].rnd) {
pushdown(p);
rs(p) = merge(rs(p), q);
updata(p); return p;
} else {
pushdown(q);
ls(q) = merge(p, ls(q));
updata(q); return q;
}
}
void split(int p, int k, int &x, int &y) {
if (!p) x = 0, y = 0;
else {
pushdown(p);
if (t[ls(p)].siz >= k) y = p, split(ls(p), k, x, ls(p));
else x = p, split(rs(p), k - t[ls(p)].siz - 1, rs(p), y);
updata(p);
}
}
int build(int l, int r) { // build tree on a[l..r], return the root
if (l > r) return 0;
return merge(build(l, mid - 1), merge(newnode(a[mid]), build(mid + 1, r)));
}
/*
other functions base on split() and merge()
*/
int main() {
}
#include <bits/stdc++.h>
using namespace std;
template<typename DataType, int N = 100010>
struct fhq_Treap {
private:
const DataType inf; //inf的定义
struct node {
DataType key; int rnd;
int siz, l, r;
} d[N];
int rt = 0, tot;
void updata(int t) {
d[t].siz = d[d[t].l].siz + d[d[t].r].siz + 1;
}
pair<int, int> split(int t, int p) {
pair<int, int> res(0, 0);
if (t == 0) return res;
if (p <= d[d[t].l].siz) {
res = split(d[t].l, p);
d[t].l = res.second;
updata(t);
res.second = t;
} else {
res = split(d[t].r, p - 1 - d[d[t].l].siz);
d[t].r = res.first;
updata(t);
res.first = t;
}
return res;
}
int merge(int a, int b) {
if (a == 0) return b;
if (b == 0) return a;
if (d[a].rnd < d[b].rnd) {
d[a].r = merge(d[a].r, b);
updata(a);
return a;
}
d[b].l = merge(a, d[b].l);
updata(b);
return b;
}
int x_rank(int t, DataType key) {
if (t == 0) return 1;
if (!(d[t].key < key)) return x_rank(d[t].l, key); //key<=d[t].key
return d[d[t].l].siz + 1 + x_rank(d[t].r, key);
}
DataType getkey(int t, int rk) {
if (rk <= d[d[t].l].siz) return getkey(d[t].l, rk);
if (rk == d[d[t].l].siz + 1) return d[t].key;
return getkey(d[t].r, rk - d[d[t].l].siz - 1);
}
int pre(int t, DataType key, int res = 0) {
if (t == 0) return res;
if (d[t].key < key) return pre(d[t].r, key, t);
return pre(d[t].l, key, res);
}
int nxt(int t, DataType key, int res = 0) {
if (t == 0) return res;
if (key < d[t].key) return nxt(d[t].l, key, t);
return nxt(d[t].r, key, res);
}
int newnode(DataType key) {
d[++tot] = {key, rand(), 1, 0, 0};
return tot;
}
public:
void build() {
rt = tot = 0;
srand(time(0));
rt = newnode(inf); //这里需要修改
d[rt].l = newnode(-inf);
updata(rt);
}
void insert(DataType key) {
int k = x_rank(rt, key);
pair<int, int> a = split(rt, k - 1);
rt = merge(merge(a.first, newnode(key)), a.second);
}
void remove(DataType key) {
int k = x_rank(rt, key);
pair<int, int> a = split(rt, k - 1), b = split(a.second, 1);
rt = merge(a.first, b.second);
}
int getrank(DataType key) {
return x_rank(rt, key);
}
DataType getpre(DataType key) {
return d[pre(rt, key)].key;
}
DataType getnxt(DataType key) {
return d[nxt(rt, key)].key;
}
DataType getkey(int rk) {
return getkey(rt, rk);
}
int getroot() {
return rt;
}
};
#include <cstring>
typedef long long ll;
namespace hashtable1 {
const int M = 19260817;
const int MAX_SIZE = 2000000;
struct Hash_map {
struct data {
int nxt;
ll key, value; // (key,value)
} e[MAX_SIZE];
int head[M], size;
inline int f(ll key) { return key % M; } // 哈希函数
ll &operator[](const ll &key) { // 重载[]
int ky = f(key);
for (int i = head[ky]; i != -1; i = e[i].nxt)
if (e[i].key == key) return e[i].value;
return e[++size] = data{head[ky], key, 0}, head[ky] = size, e[size].value;
}
void clear() { // 清空
memset(head, -1, sizeof(head));
size = 0;
}
Hash_map() {clear();} // 初始化清空
};
}
namespace hashtable2 {
const int M = 19260817;
const int MAX_SIZE = 2000000;
struct Hash {
struct data {
int nxt;
ll key, value;
} e[MAX_SIZE];
int head[M], size;
inline int f(ll key) { return key % M; } // 哈希函数
void clear() { // 清空
memset(head, -1, sizeof(head));
size = 0;
}
ll query(ll key) { // 查询
for (int i = head[f(key)]; i != -1; i = e[i].nxt)
if (e[i].key == key) return e[i].value;
return -1;
}
ll modify(ll key, ll value) { // 修改
for (int i = head[f(key)]; i != -1; i = e[i].nxt)
if (e[i].key == key) return e[i].value = value;
return -1;
}
ll insert(ll key, ll value) { // 插入
if (query(key) != -1) return -1;
e[++size] = data{head[f(key)], key, value};
head[f(key)] = size;
return value;
}
};
}
/*
luogu P4357 [CQOI2016]K 远点对
K-D Tree 二维平面邻域查询
题意:平面上 N (1e5) 个点,求第 K (1e2) 远点对距离
*/
#include <bits/stdc++.h>
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
using namespace std;
typedef double db;
typedef long long ll;
const int N = 100010;
int n, k;
priority_queue<ll, vector<ll>, greater<ll> >q;
template <typename _Tp> inline void umin(_Tp &x, _Tp y) {(x > y) &&(x = y);}
template <typename _Tp> inline void umax(_Tp &x, _Tp y) {(x < y) &&(x = y);}
namespace KDTree {
struct node {
int X[2];
int &operator[](const int k) {return X[k];}
} p[N];
int nowd;
bool cmp(node a, node b) {return a.X[nowd] < b.X[nowd];}
int lc[N], rc[N], L[N][2], R[N][2]; // lc/rc 左右孩子;L/R 对应超矩形各个维度范围
inline ll sqr(int x) {return 1ll * x * x;}
void pushup(int x) { // 更新该点所代表空间范围
L[x][0] = R[x][0] = p[x][0];
L[x][1] = R[x][1] = p[x][1];
if (lc[x]) {
umin(L[x][0], L[lc[x]][0]); umax(R[x][0], R[lc[x]][0]);
umin(L[x][1], L[lc[x]][1]); umax(R[x][1], R[lc[x]][1]);
}
if (rc[x]) {
umin(L[x][0], L[rc[x]][0]); umax(R[x][0], R[rc[x]][0]);
umin(L[x][1], L[rc[x]][1]); umax(R[x][1], R[rc[x]][1]);
}
}
int build(int l, int r) {
if (l > r) return 0;
int mid = (l + r) >> 1;
// >>> 方差建树
db av[2] = {0, 0}, va[2] = {0, 0}; // av 平均数,va 方差
for (int i = l; i <= r; ++i) av[0] += p[i][0], av[1] += p[i][1];
av[0] /= (r - l + 1); av[1] /= (r - l + 1);
for (int i = l; i <= r; ++i) {
va[0] += sqr(av[0] - p[i][0]);
va[1] += sqr(av[1] - p[i][1]);
}
if (va[0] > va[1]) nowd = 0;
else nowd = 1; // 找方差大的维度划分
// >>> 轮换建树 nowd=dep%D
nth_element(p + l, p + mid, p + r + 1, cmp); // 以该维度中位数分割
lc[mid] = build(l, mid - 1); rc[mid] = build(mid + 1, r);
pushup(mid);
return mid;
}
ll dist(int a, int x) { // 估价函数,点 a 到树上 x 点对应空间最远距离
return max(sqr(p[a][0] - L[x][0]), sqr(p[a][0] - R[x][0])) +
max(sqr(p[a][1] - L[x][1]), sqr(p[a][1] - R[x][1]));
}
void query(int l, int r, int a) { // 点 a 邻域查询
if (l > r) return ;
int mid = (l + r) >> 1;
ll t = sqr(p[mid][0] - p[a][0]) + sqr(p[mid][1] - p[a][1]);
if (t > q.top()) q.pop(), q.push(t); // 更新答案
ll disl = dist(a, lc[mid]), disr = dist(a, rc[mid]);
if (disl > q.top() && disr > q.top()) // 两边都有机会更新,优先搜大的
(disl > disr) ? (query(l, mid - 1, a), query(mid + 1, r, a)) : (query(mid + 1, r, a), query(l, mid - 1, a));
else
(disl > q.top()) ? query(l, mid - 1, a) : query(mid + 1, r, a);
}
}
using namespace KDTree;
int main() {
red(n); red(k); k *= 2;
for (int i = 1; i <= k; ++i) q.push(0);
for (int i = 1; i <= n; ++i) red(p[i][0]), red(p[i][1]);
build(1, n);
for (int i = 1; i <= n; ++i) query(1, n, i);
printf("%lld\n", q.top());
}
/*
K-D Tree 维护空间权值 (单点修改 & 空间查询)
时间复杂度 O(log n) ~ O(n^(1-1/k))
*/
#include <bits/stdc++.h>
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
using namespace std;
const int N = 200010;
typedef double db;
template <typename _Tp> void umin(_Tp &x, _Tp y) {if (x > y) x = y;}
template <typename _Tp> void umax(_Tp &x, _Tp y) {if (x < y) x = y;}
template <typename _Tp> _Tp sqr(_Tp x) {return x * x;}
namespace KDT {
struct dat {
int X[2];
int &operator[](const int k) {return X[k];}
} p[N];
db alp = 0.725; // 重构常数
int nowd;
bool cmp(int a, int b) {return p[a][nowd] < p[b][nowd];}
int root, cur, d[N], lc[N], rc[N], L[N][2], R[N][2], siz[N], sum[N], val[N];
// root:根 cur:总点数 d:当前分割维度 lc/rc:左右儿子 L/R:当前空间范围 siz:子树大小 sum/val 空间的值,单点的值
int g[N], t; // 用于重构的临时数组
void pushup(int x) {
siz[x] = siz[lc[x]] + siz[rc[x]] + 1;
sum[x] = sum[lc[x]] + sum[rc[x]] + val[x];
L[x][0] = R[x][0] = p[x][0];
L[x][1] = R[x][1] = p[x][1];
if (lc[x]) {
umin(L[x][0], L[lc[x]][0]); umax(R[x][0], R[lc[x]][0]);
umin(L[x][1], L[lc[x]][1]); umax(R[x][1], R[lc[x]][1]);
}
if (rc[x]) {
umin(L[x][0], L[rc[x]][0]); umax(R[x][0], R[rc[x]][0]);
umin(L[x][1], L[rc[x]][1]); umax(R[x][1], R[rc[x]][1]);
}
}
int build(int l, int r) { // 对 g[1...t] 进行建树 ,!!注意了,对应点都是 g[x]
if (l > r) return 0;
int mid = (l + r) >> 1;
db av[2] = {0, 0}, va[2] = {0, 0};
for (int i = l; i <= r; ++i) av[0] += p[g[i]][0], av[1] += p[g[i]][1];
av[0] /= (r - l + 1); av[1] /= (r - l + 1);
for (int i = l; i <= r; ++i) va[0] += sqr(av[0] - p[g[i]][0]), va[1] += sqr(av[1] - p[g[i]][1]);
if (va[0] > va[1]) d[g[mid]] = nowd = 0;
else d[g[mid]] = nowd = 1;
nth_element(g + l, g + mid, g + r + 1, cmp);
lc[g[mid]] = build(l, mid - 1); rc[g[mid]] = build(mid + 1, r);
pushup(g[mid]);
return g[mid];
}
void expand(int x) { // 将子树展开到临时数组里
if (!x) return;
expand(lc[x]);
g[++t] = x;
expand(rc[x]);
}
void rebuild(int &x) { // x 所在子树重构
t = 0; expand(x);
x = build(1, t);
}
bool chk(int x) {return alp * siz[x] <= (db)max(siz[lc[x]], siz[rc[x]]);} // 判断失衡
void insert(int &x, int a) { // 插入点 a , p[a],val[a] 为其信息
if (!x) { x = a; pushup(x); d[x] = rand() & 1; return; }
if (p[a][d[x]] <= p[x][d[x]]) insert(lc[x], a);
else insert(rc[x], a);
pushup(x);
if (chk(x)) rebuild(x); // 失衡暴力重构
}
dat Lt, Rt; // 询问一块空间的值(为了减小常数把参数放在外面)
int query(int x) {
if (!x || Rt[0] < L[x][0] || Lt[0] > R[x][0] || Rt[1] < L[x][1]
|| Lt[1] > R[x][1]) return 0; // 结点为空或与询问取间无交
if (Lt[0] <= L[x][0] && R[x][0] <= Rt[0] && Lt[1] <= L[x][1]
&& R[x][1] <= Rt[1]) return sum[x]; // 区间完全覆盖
int ret = 0;
if (Lt[0] <= p[x][0] && p[x][0] <= Rt[0] && Lt[1] <= p[x][1]
&& p[x][1] <= Rt[1]) ret += val[x]; // 当前点在区间内
return query(lc[x]) + query(rc[x]) + ret;
}
}
using namespace KDT;
int n, lstans;
int main() {
red(n);
for (int op;;) {
red(op);
switch (op) {
case 1:
++cur; red(p[cur][0]); red(p[cur][1]); red(val[cur]);
p[cur][0] ^= lstans; p[cur][1] ^= lstans; val[cur] ^= lstans;
insert(root, cur);
break;
case 2:
red(Lt[0]); red(Lt[1]); red(Rt[0]); red(Rt[1]);
Lt[0] ^= lstans; Lt[1] ^= lstans; Rt[0] ^= lstans; Rt[1] ^= lstans;
printf("%d\n", lstans = query(root));
break;
case 3: return 0; break;
}
}
return 0;
}
// Link Cut Tree
#include <cstdio>
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
template <typename _Tp> void swap(_Tp &x, _Tp &y) {_Tp tmp = x; x = y; y = tmp;}
const int N = 100010;
namespace LCT {
int ch[N][2], f[N], sum[N], val[N], tag[N], dat[N]; // dat 维护的链信息, val 点上信息
inline void PushUp(int x) {
dat[x] = dat[ch[x][0]] ^ dat[ch[x][1]] ^ val[x];
}
inline void PushRev(int x) {swap(ch[x][0], ch[x][1]); tag[x] ^= 1;}
inline void PushDown(int x) {
if (tag[x] == 0) return ;
PushRev(ch[x][0]); PushRev(ch[x][1]); tag[x] = 0;
}
inline bool Get(int x) {return ch[f[x]][1] == x;} // 是父亲的哪个儿子
inline bool IsRoot(int x) {return (ch[f[x]][1] != x && ch[f[x]][0] != x);} // 是否是当前 Splay 的根
inline void Rotate(int x) { // Splay 旋转
int y = f[x], z = f[y], k = Get(x);
if (!IsRoot(y)) ch[z][Get(y)] = x;
ch[y][k] = ch[x][k ^ 1]; f[ch[x][k ^ 1]] = y;
ch[x][k ^ 1] = y; f[y] = x; f[x] = z;
PushUp(y); PushUp(x);
}
void Updata(int x) { // Splay 中从上到下 PushDown
if (!IsRoot(x)) Updata(f[x]);
PushDown(x);
}
inline void Splay(int x) { // Splay 上把 x 转到根
Updata(x);
for (int fa; fa = f[x], !IsRoot(x); Rotate(x)) {
if (!IsRoot(fa)) Rotate(Get(fa) == Get(x) ? fa : x);
}
PushUp(x);
}
inline void Access(int x) { // 辅助树上打通 x 到根的路径(即 x 到根变为实链)
for (int p = 0; x; p = x, x = f[x]) {
Splay(x); ch[x][1] = p; PushUp(x);
}
}
inline void MakeRoot(int x) { // 钦定 x 为辅助树根
Access(x); Splay(x); PushRev(x);
}
inline int FindRoot(int x) { // 找 x 所在辅助树根
Access(x); Splay(x);
while (ch[x][0]) PushDown(x), x = ch[x][0];
Splay(x); // 不加复杂度会假
return x;
}
inline void Split(int x, int y) { // 把 x 到 y 的路径提出来, 并以 y 为 Splay 根
MakeRoot(x); Access(y); Splay(y);
}
inline bool Link(int x, int y) { // 连接 x,y 两点
MakeRoot(x);
if (FindRoot(y) == x) return false;
f[x] = y;
return true;
}
inline bool Cut(int x, int y) { // x,y 断边
MakeRoot(x);
if (FindRoot(y) == x && f[y] == x && !ch[y][0]) {
f[y] = ch[x][1] = 0; PushUp(x);
return true;
}
return false;
}
// 如果保证合法
/*
inline void Link(int x,int y) {
MakeRoot(x); MakeRoot(y); f[x]=y;
}
inline void Cut(int x,int y) {
MakeRoot(x); Access(y); Splay(y); ch[y][0]=f[x]=0;
}
*/
/*
void Print(int x) {
if(ch[x][0]) Print(ch[x][0]);
printf("%d,",x);
if(ch[x][1]) Print(ch[x][1]);
}
*/
}
using namespace LCT;
int n, m;
int main() {
red(n); red(m);
for (int i = 1; i <= n; ++i) red(val[i]);
for (int i = 1; i <= m; ++i) {
int op, x, y; red(op); red(x); red(y);
switch (op) {
case 0: Split(x, y); printf("%d\n", dat[y]); break;
case 1: Link(x, y); break;
case 2: Cut(x, y); break;
case 3: Splay(x); val[x] = y; break;
}
}
}
/* 左偏树 (可并堆)
+ 左偏树是一棵二叉树,有堆的性质
+ 每个节点左儿子dist >= 右儿子dist
+ 每个节点的 dist 都等于其右儿子的 dist 加一
*/
#include <bits/stdc++.h>
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
using namespace std;
const int N = 100010;
struct node {
int rt, ch[2], d, val;
/* other tags */
node() {}
} t[N];
int n, m;
void settag(int x, int vl) {
if (!x) { /* set tag */ }
}
void pushdown(int x) {
/* pushdown tags */
}
int merge(int x, int y) {
if (!x || !y) return x + y;
if (t[x].val > t[y].val || (t[x].val == t[y].val && x > y)) swap(x, y);
pushdown(x); rs(x) = merge(rs(x), y); t[x].rt = t[ls(x)].rt = t[rs(x)].rt = x;
if (t[ls(x)].d < t[rs(x)].d) swap(ls(x), rs(x));
t[x].d = t[rs(x)].d + 1;
return x;
}
int pop(int x) {
pushdown(x);
return merge(t[x].ch[0], t[x].ch[1]);
}
int findrt(int u) {return u == t[u].rt ? u : t[u].rt = findrt(t[u].rt);}
int main() {
return 0;
}
// 李超线段树 luogu-P4097 [HEOI2013]Segment
#include <bits/stdc++.h>
#define ls (x<<1)
#define rs (x<<1|1)
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
using namespace std;
typedef long long ll;
typedef double db;
const int N = 100010;
const int M = 40000;
struct line {
db k, b;
} lin[N];
db val(int id, db X) {return lin[id].k * X + lin[id].b;}
int D[N << 2], n, id;
void modify(int L, int R, int id, int l = 1, int r = M - 1, int x = 1) {
if (L <= l && r <= R) {
int mid = (l + r) >> 1, lid = D[x];
db lst = val(D[x], mid), now = val(id, mid);
if (l == r) {if (now > lst) D[x] = id; return ;}
if (lin[id].k > lin[D[x]].k) {
if (now > lst) D[x] = id, modify(L, R, lid, l, mid, ls); // id->lid
else modify(L, R, id, mid + 1, r, rs);
} else if (lin[id].k < lin[D[x]].k) {
if (now > lst) D[x] = id, modify(L, R, lid, mid + 1, r, rs); // id->lid
else modify(L, R, id, l, mid, ls);
} else if (lin[id].b > lin[D[x]].k) D[x] = id;
return ;
}
int mid = (l + r) >> 1;
if (L <= mid) modify(L, R, id, l, mid, x << 1);
if (R > mid) modify(L, R, id, mid + 1, r, x << 1 | 1);
}
int gmax(int x, int y, int ps) {
if (val(x, ps) > val(y, ps)) return x;
if (val(x, ps) < val(y, ps)) return y;
return (x < y) ? x : y;
}
int query(int ps, int l = 1, int r = M - 1, int x = 1) {
if (l == r) return D[x];
int mid = (l + r) >> 1, ret = D[x], t = 0;
if (ps <= mid)
t = query(ps, l, mid, ls);
else
t = query(ps, mid + 1, r, rs);
return gmax(ret, t, ps);
}
int main() {
red(n);
int lstans = 0, tot = 0;
for (int i = 1; i <= n; ++i) {
int op; red(op);
if (op == 0) {
++tot; int k; red(k); // 询问 x=k 最大交点
k = (k + lstans - 1) % 39989 + 1;
lstans = query(k);
printf("%d\n", lstans);
} else {
int x0, y0, x1, y1; ++id; // 添加线段
red(x0); red(y0); red(x1); red(y1);
x0 = (x0 + lstans - 1) % 39989 + 1; x1 = (x1 + lstans - 1) % 39989 + 1;
y0 = (y0 + lstans - 1) % (int)(1e9) + 1; y1 = (y1 + lstans - 1) % (int)(1e9) + 1;
if (x0 > x1) swap(x0, x1), swap(y0, y1);
if (x0 == x1) {
lin[id].k = 0; lin[id].b = max(y1, y0);
} else {
lin[id].k = (db)(y1 - y0) / (db)(x1 - x0);
lin[id].b = (db)y1 - lin[id].k * (db)x1;
}
modify(x0, x1, id);
}
}
return 0;
}
/*
__gnu_pbds :: priority_queue 堆 使用指南
========================================================================================================
__gnu_pbds ::priority_queue<_Tv, Cmp_Fn = std::less<_Tv>, Tag = pairing_heap_tag,
Allocator = std::allocator<char> >
_Tv: 储存的元素类型
Cmp_Fn: 比较函子,默认 std::less<_Tv> 为大根堆
Tag: 堆的类型(默认且建议 pairing_heap_tag)
Allocator: 空间分配器类型(不用改)
push(),pop(),top(),size(),empty() 与 std::priority_queue 类似
join(other) 将 other 加入当前堆,other 堆被删除(前提是两棵树的类型一样)
modify(it, key) 修改迭代器 it 所指的 key,并对底层储存结构进行排序
erase(it) 把迭代器 it 位置的键值从堆中擦除
begin(),end() 返回可以用来遍历的迭代器,不保证有序!且只要进行过修改操作就会变
========================================================================================================
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
const int N = 100010;
__gnu_pbds::priority_queue<pair<int, int>, greater<pair<int, int>>> Q[N];
// 以下是用 pb_ds::tree 实现的 【模板】左偏树(可并堆) https://www.luogu.com.cn/problem/P3377
int fa[N], n, m;
bool del[N];
int find(int u) {
return fa[u] == u ? u : fa[u] = find(fa[u]);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
int x; scanf("%d", &x);
fa[i] = i, Q[i].push({x, i});
}
while (m--) {
int op, x, y;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &x, &y);
if (del[x] || del[y]) continue;
x = find(x), y = find(y);
if (x != y) {
fa[x] = y;
Q[y].join(Q[x]);
}
} else {
scanf("%d", &x);
if (del[x]) {
puts("-1");
continue;
}
x = find(x);
printf("%d\n", Q[x].top().first);
del[Q[x].top().second] = 1;
Q[x].pop();
}
}
}
/*
__gnu_pbds :: tree 平衡树 使用指南
========================================================================================================
__gnu_pbds ::tree<Key, Mapped, Cmp_Fn = std::less<Key>, Tag = rb_tree_tag,
Node_Update = null_tree_node_update,
Allocator = std::allocator<char> >
Key: 储存的元素类型
Mapped: 填 null_type 当成 std::set, 填其他类型当成 std::map
Cmp_Fn: 比较函子
Tag: 树的类型(建议 rb_tree_tag)
Node_Update: 更新节点的策略,默认是 null_tree_node_update
使用 tree_order_statistics_node_update 来允许 order_of_key,find_by_order 方法
Allocator: 空间分配器类型(不用改)
insert(),erase(),lower_bound(),upper_bound(),find(),empty(),size(),begin(),end() 与 std::set 类似
join(other) 将 other 加入当前树,other 树被删除(前提是两棵树的类型一样)
split(val, other) 以 Cmp_Fn 比较,小于等于 val 的属于当前树,其余的属于 other 树
order_of_key(x) 返回 x 以 Cmp_Fn 比较的排名(从 0 开始)
find_by_order(x) 返回 Cmp_Fn 比较的排名所对应元素的迭代器 (从 0 开始)
========================================================================================================
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
__gnu_pbds::tree<std::pair<int, int>, __gnu_pbds::null_type, std::less<std::pair<int, int>>,
__gnu_pbds::rb_tree_tag,
__gnu_pbds::tree_order_statistics_node_update> T;
// 以下是用 pb_ds::tree 实现的 【模板】普通平衡树 https://www.luogu.com.cn/problem/P3369
int Q;
int main() {
scanf("%d", &Q);
while (Q--) {
int opt, x; scanf("%d%d", &opt, &x);
switch (opt) {
case 1: {
auto it = T.lower_bound({x + 1, 0});
if (it != T.begin() && (--it)->first != x) T.insert({x, 1});
else T.insert({x, it->second + 1});
break;
}
case 2: {
auto it1 = --T.lower_bound({x + 1, 0});
T.erase(it1);
break;
}
case 3: {
int rk = T.order_of_key({x, 1});
printf("%d\n", rk + 1);
break;
}
case 4: {
auto it = T.find_by_order(x - 1);
printf("%d\n", it->first);
break;
}
case 5: {
auto it = --T.lower_bound({x, 0});
printf("%d\n", it->first);
break;
}
case 6: {
auto it = T.lower_bound({x + 1, 0});
printf("%d\n", it->first);
break;
}
default:
break;
}
// for (auto i : T) {
// printf("%d[%d] ", i.first, i.second);
// }
// puts("");
}
return 0;
}
// 可持久化数组
#include <cstdio>
#define ls(p) tr[p].lc
#define rs(p) tr[p].rc
#define re register
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
using namespace std;
const int N = 1000010;
struct node {
int lc, rc, val;
} tr[N * 21]; int tot;
int root[N];
int n, m, a[N];
int newnode() {
tr[++tot] = {0, 0, 0};
return tot;
}
void build(int p, int l = 1, int r = n) {
if (l == r) return tr[p].val = a[l], void();
int mid = (l + r) >> 1;
build(ls(p) = newnode(), l, mid);
build(rs(p) = newnode(), mid + 1, r);
}
void modify(int p, int q, int pos, int val, int l = 1, int r = n) {
if (l == r) return tr[q].val = val, void();
int mid = (l + r) >> 1;
if (pos <= mid) {
modify(ls(p), ls(q) = newnode(), pos, val, l, mid);
rs(q) = rs(p);
} else {
modify(rs(p), rs(q) = newnode(), pos, val, mid + 1, r);
ls(q) = ls(p);
}
}
int query(int p, int pos, int l = 1, int r = n) {
if (l == r) return tr[p].val;
int mid = (l + r) >> 1;
if (pos <= mid) return query(ls(p), pos, l, mid);
else return query(rs(p), pos, mid + 1, r);
}
int main() {
red(n); red(m);
for (re int i = 1; i <= n; ++i) red(a[i]);
root[0] = newnode(); build(root[0]);
for (re int i = 1; i <= m; ++i) {
re int v, op, loc, vl;
red(v); red(op); red(loc);
if (op == 1) {
red(vl);
modify(root[v], root[i] = newnode(), loc, vl);
} else {
printf("%d\n", query(root[v], loc));
root[i] = root[v];
}
}
}
#include <cstdio>
#include <iostream>
#define ls(p) tr[p].lc
#define rs(p) tr[p].rc
#define re register
using namespace std;
const int N = 200010;
struct node {
int lc, rc, val, siz;
} tr[N * 41];
int root[N], tot;
int n, m;
int newnode() {
tr[++tot] = {0, 0, 0};
return tot;
}
void build(int p, int l = 1, int r = n) {
if (l == r) return tr[p].val = l, tr[p].siz = 1, void();
int mid = (l + r) >> 1;
build(ls(p) = newnode(), l, mid);
build(rs(p) = newnode(), mid + 1, r);
}
void modify_fa(int p, int q, int pos, int val, int l = 1, int r = n) {
if (l == r) return tr[q].val = val, tr[q].siz = tr[p].siz, void();
int mid = (l + r) >> 1;
if (pos <= mid) {
modify_fa(ls(p), ls(q) ? ls(q) : ls(q) = newnode(), pos, val, l, mid);
if (rs(q) == 0)rs(q) = rs(p);
} else {modify_fa(rs(p), rs(q) ? rs(q) : rs(q) = newnode(), pos, val, mid + 1, r); if (ls(q) == 0)ls(q) = ls(p);}
}
void modify_dep(int p, int q, int pos, int siz, int l = 1, int r = n) {
if (l == r) return tr[q].siz = siz, tr[q].val = tr[p].val, void();
int mid = (l + r) >> 1;
if (pos <= mid) {
modify_dep(ls(p), ls(q) ? ls(q) : ls(q) = newnode(), pos, siz, l, mid);
if (rs(q) == 0)rs(q) = rs(p);
} else {modify_dep(rs(p), rs(q) ? rs(q) : rs(q) = newnode(), pos, siz, mid + 1, r); if (ls(q) == 0)ls(q) = ls(p);}
}
// return the node number
int query(int p, int pos, int l = 1, int r = n) {
if (l == r) return p;
int mid = (l + r) >> 1;
if (pos <= mid) return query(ls(p), pos, l, mid);
else return query(rs(p), pos, mid + 1, r);
}
int find(int rt, int u) {
int pa = query(rt, u);
if (tr[pa].val == u) return u;
return find(rt, tr[pa].val);
}
int main() {
scanf("%d%d", &n, &m);
root[0] = newnode(); build(root[0]);
for (re int i = 1; i <= m; ++i) {
re int opt, a, b;
scanf("%d%d", &opt, &a);
if (opt == 1) { // 合并 a,b
scanf("%d", &b);
root[i] = newnode();
int f1 = find(root[i - 1], a), f2 = find(root[i - 1], b);
int sz1 = tr[query(root[i - 1], f1)].siz, sz2 = tr[query(root[i - 1], f2)].siz;
if (f1 != f2) {
if (sz1 > sz2) swap(f1, f2), swap(sz1, sz2);
modify_fa(root[i - 1], root[i], f1, f2);
modify_dep(root[i - 1], root[i], f2, sz1 + sz2);
} else
root[i] = root[i - 1];
}
if (opt == 2) // 回到状态 a
root[i] = root[a];
if (opt == 3) { // 询问 a,b 是否在同一集合
scanf("%d", &b);
root[i] = root[i - 1];
int f1 = find(root[i], a), f2 = find(root[i], b);
printf("%d\n", f1 == f2);
}
}
return 0;
}
// 主席树,区间第 k 大
#include <cstdio>
#include <algorithm>
#define ls(p) tr[p].lc
#define rs(p) tr[p].rc
#define re register
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
using namespace std;
const int N = 200010;
struct node {
int cnt, lc, rc;
} tr[N * 18]; int root[N], tot;
int a[N], b[N], tt, n, q;
int newnode() { tr[++tot] = {0, 0, 0}; return tot;}
void pushup(int p) {tr[p].cnt = tr[ls(p)].cnt + tr[rs(p)].cnt;}
void modify(int p, int q, int val, int l = 1, int r = tt) {
if (l == r) return (p == 0) ? tr[q].cnt = 1 : tr[q].cnt = tr[p].cnt + 1, void();
int mid = (l + r) >> 1;
if (val <= mid) {
modify(ls(p), ls(q) = newnode(), val, l, mid);
rs(q) = rs(p);
} else {
modify(rs(p), rs(q) = newnode(), val, mid + 1, r);
ls(q) = ls(p);
}
pushup(q);
}
int query(int p, int q, int k, int l = 1, int r = tt) {
if (l == r) return b[l];
int mid = (l + r) >> 1, t = tr[ls(q)].cnt - tr[ls(p)].cnt;
return (k <= t) ? query(ls(p), ls(q), k, l, mid) : query(rs(p), rs(q), k - t, mid + 1, r);
}
int main() {
red(n); red(q);
for (re int i = 1; i <= n; ++i) red(a[i]), b[i] = a[i];
sort(b + 1, b + n + 1);
tt = unique(b + 1, b + n + 1) - b - 1;
for (re int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + tt + 1, a[i]) - b;
root[0] = newnode();
for (re int i = 1; i <= n; ++i) {
root[i] = newnode();
modify(root[i - 1], root[i], a[i]);
}
for (re int i = 1; i <= q; ++i) {
re int l, r, k; red(l); red(r); red(k);
printf("%d\n", query(root[l - 1], root[r], k));
}
return 0;
}
// 期望 O(n)-O(1) RMQ
// luogu P3793 由乃救爷爷
#include <cstdio>
#define re register
// -------------- ReadIN ----------------
namespace GenHelper {
unsigned z1, z2, z3, z4, b;
unsigned rand_() {
b = ((z1 << 6)^z1) >> 13;
z1 = ((z1 & 4294967294U) << 18)^b;
b = ((z2 << 2)^z2) >> 27;
z2 = ((z2 & 4294967288U) << 2)^b;
b = ((z3 << 13)^z3) >> 21;
z3 = ((z3 & 4294967280U) << 7)^b;
b = ((z4 << 3)^z4) >> 12;
z4 = ((z4 & 4294967168U) << 13)^b;
return (z1 ^ z2 ^ z3 ^ z4);
}
}
void srand(unsigned x) {using namespace GenHelper; z1 = x; z2 = (~x) ^ 0x233333333U; z3 = x ^ 0x1234598766U; z4 = (~x) + 51;}
int read() {
using namespace GenHelper;
int a = rand_() & 32767;
int b = rand_() & 32767;
return a * 32768 + b;
}
// ----------- END ReadIN -------------
typedef unsigned long long ull;
int n, m, s;
// ------------ BEGIN RMQ -------------
const int N = 20000010;
int a[N];
namespace RMQ {
inline int gmax(int x, int y) {return a[x] > a[y] ? x : y;}
const int B = 4434; // B 大概取 log2(n) or sqrt(n) ?? 怕被卡的话随机微调块长
const int M = 16;
int bl[N], F[M][N / B + 10], ps[N], pre[N], suf[N], LOG[N], tot;
// bl 属于哪个块,F 块间ST表 ps块内最值下标 pre/suf 块内前缀/后缀最值
void init() {
for (re int i = 1; i <= n; ++i) bl[i] = (i - 1) / B + 1;
for (re int i = 1; i <= n;
++i)(bl[i] != bl[i - 1]) ? (pre[i] = i, ps[bl[i - 1]] = pre[i - 1]) : (pre[i] = gmax(pre[i - 1], i));
for (re int i = 1, j = B; j <= n; ++i, j += B) ps[i] = pre[j];
tot = bl[n]; ps[tot] = pre[n];
for (re int i = n; i >= 1; --i)(bl[i] != bl[i + 1]) ? (suf[i] = i) : (suf[i] = gmax(suf[i + 1], i));
LOG[0] = -1;
for (re int i = 1; i <= tot; ++i) LOG[i] = LOG[i >> 1] + 1;
for (re int i = 1; i <= tot; ++i) F[0][i] = ps[i];
for (re int j = 1; j <= LOG[tot]; ++j) {
for (re int i = 1; i <= tot; ++i) {
if (i + (1 << j) - 1 > tot) break;
F[j][i] = gmax(F[j - 1][i], F[j - 1][i + (1 << (j - 1))]);
}
}
}
inline int ask(int l, int r) { // 返回区间最值位置
if (bl[l] == bl[r]) {
int p = l;
for (re int i = l + 1; i <= r; ++i) p = gmax(p, i);
return p;
}
if (bl[l] + 1 == bl[r]) return gmax(suf[l], pre[r]);
int L = bl[l] + 1, R = bl[r] - 1;
int k = LOG[R - L + 1];
return gmax(gmax(F[k][L], F[k][R - (1 << k) + 1]), gmax(suf[l], pre[r]));
}
}
// -------------- END RMQ --------------
inline void swap(int &l, int &r) {l ^= r; r ^= l; l ^= r;}
int main() {
scanf("%d%d%d", &n, &m, &s);
srand(s);
for (re int i = 1; i <= n; ++i) a[i] = read();
RMQ::init();
ull ANS = 0;
for (re int i = 1, l, r; i <= m; ++i) {
l = read() % n + 1, r = read() % n + 1;
(l > r) &&(swap(l, r), 1);
ANS += a[RMQ::ask(l, r)];
}
printf("%llu\n", ANS);
}
/*
* seg-beats 吉司机线段树
* 区间最值操作
* 支持 区间取min,区间取max,区间加减,区间求和,区间最小/大
* 复杂度 O(m log n)
*/
#include <bits/stdc++.h>
#define ls (x << 1)
#define rs (x << 1 | 1)
#define mid ((l + r) >> 1)
template <typename Tp>
inline void read(Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fg ^= 1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template <typename Tp, typename... Args>
void read(Tp &t, Args &...args) { read(t); read(args...); }
template <typename Tp>
inline void write(Tp x, char ch = '\n') {
static char buf[128]; int tot = 0;
if (x < 0) x = -x, putchar('-');
while (x) buf[tot++] = '0' + x % 10, x /= 10;
if (tot == 0) putchar('0');
while (tot--) putchar(buf[tot]);
if (ch) putchar(ch);
}
using namespace std;
typedef long long ll;
const int N = 500010;
const int inf = 0x3f3f3f3f;
struct datmn {
int fi, se, cnt;
datmn() {fi = se = inf; cnt = 0;}
void ins(int x, int c) {
if (x < fi) se = fi, cnt = c, fi = x;
else if (x == fi) cnt += c;
else if (x < se) se = x;
}
friend datmn operator+(const datmn &a, const datmn &b) {
datmn r = a; r.ins(b.fi, b.cnt); r.ins(b.se, 0); return r;
}
};
struct datmx {
int fi, se, cnt;
datmx() {fi = se = -inf; cnt = 0;}
void ins(int x, int c) {
if (x > fi) se = fi, cnt = c, fi = x;
else if (x == fi) cnt += c;
else if (x > se) se = x;
}
friend datmx operator+(const datmx &a, const datmx &b) {
datmx r = a; r.ins(b.fi, b.cnt); r.ins(b.se, 0); return r;
}
};
struct node {
datmn mn; datmx
mx; // mn: (最小值,严格次小值,最小值个数) , mx: (最大值,严格次大值,最大值个数)
ll sum; int addmn, addmx, add,
len; // sum 区间和,addmn 最小值lazytag,addmx 最大值lazytag,add 其他数 lazytag,len 区间长度
} t[N << 2];
// ostream &operator<<(ostream& out, const datmx &d) {
// return out << "dat{ " << d.fi << " (" << d.cnt << ") ," << d.se << " } ";
// }
// ostream &operator<<(ostream& out, const datmn &d) {
// return out << "dat{ " << d.fi << " (" << d.cnt << ") ," << d.se << " } ";
// }
// ostream &operator<<(ostream& out, const node &d) {
// return out << "mn" << d.mn << "mx" << d.mx << " sum=" << d.sum << " addmn=" << d.addmn << " addmx=" << d.addmx << " add=" << d.add << " ";
// }
int n, m, a[N];
void pushup(int x) {
t[x].mx = t[ls].mx + t[rs].mx;
t[x].mn = t[ls].mn + t[rs].mn;
t[x].sum = t[ls].sum + t[rs].sum;
}
void build(int l = 1, int r = n, int x = 1) {
t[x].add = t[x].addmn = t[x].addmx = 0;
t[x].len = r - l + 1;
if (l == r) {
t[x].mx = datmx(); t[x].mx.ins(a[l], 1);
t[x].mn = datmn(); t[x].mn.ins(a[l], 1);
t[x].sum = a[l];
return;
}
build(l, mid, ls); build(mid + 1, r, rs);
pushup(x);
}
void update(int x, int vn, int vx, int v) { // vn: addmn, vx: addmx, v: add
if (t[x].mn.fi ==
t[x].mx.fi) { // 所有数相同特判,此时最大值 tag 和最小值 tag 应该相同且不等于其他值 tag
if (vn == v) vn = vx;
else vx = vn;
t[x].sum += (ll)vn * t[x].mn.cnt;
} else t[x].sum += (ll)vn * t[x].mn.cnt + (ll) vx * t[x].mx.cnt + (ll)v * (t[x].len - t[x].mn.cnt -
t[x].mx.cnt);
if (t[x].mn.se == t[x].mx.fi) t[x].mn.se += vx; // 次小值 = 最大值,应该用最大值 tag 处理
else if (t[x].mn.se != inf) t[x].mn.se += v;
if (t[x].mx.se == t[x].mn.fi) t[x].mx.se += vn; // 次大值同理
else if (t[x].mx.se != -inf) t[x].mx.se += v;
t[x].mn.fi += vn; t[x].mx.fi += vx;
t[x].addmn += vn; t[x].addmx += vx; t[x].add += v;
}
void pushdown(int x) {
int mn = min(t[ls].mn.fi, t[rs].mn.fi);
int mx = max(t[ls].mx.fi, t[rs].mx.fi);
update(ls, (mn == t[ls].mn.fi) ? t[x].addmn : t[x].add, (mx == t[ls].mx.fi) ? t[x].addmx : t[x].add,
t[x].add);
update(rs, (mn == t[rs].mn.fi) ? t[x].addmn : t[x].add, (mx == t[rs].mx.fi) ? t[x].addmx : t[x].add,
t[x].add);
t[x].add = t[x].addmn = t[x].addmx = 0;
}
void modifyadd(int L, int R, int v, int l = 1, int r = n, int x = 1) {
if (r < L || R < l) return ;
if (L <= l && r <= R) return update(x, v, v, v);
pushdown(x);
modifyadd(L, R, v, l, mid, ls);
modifyadd(L, R, v, mid + 1, r, rs);
pushup(x);
}
void modifymin(int L, int R, int v, int l = 1, int r = n, int x = 1) {
if (r < L || R < l) return ;
if (L <= l && r <= R && v > t[x].mx.se) {
if (v >= t[x].mx.fi) return ;
update(x, 0, v - t[x].mx.fi, 0);
return;
}
pushdown(x);
modifymin(L, R, v, l, mid, ls);
modifymin(L, R, v, mid + 1, r, rs);
pushup(x);
}
void modifymax(int L, int R, int v, int l = 1, int r = n, int x = 1) {
if (r < L || R < l) return ;
if (L <= l && r <= R && v < t[x].mn.se) {
if (v <= t[x].mn.fi) return;
update(x, v - t[x].mn.fi, 0, 0);
return;
}
pushdown(x);
modifymax(L, R, v, l, mid, ls);
modifymax(L, R, v, mid + 1, r, rs);
pushup(x);
}
int querymax(int L, int R, int l = 1, int r = n, int x = 1) {
if (r < L || R < l) return -inf;
if (L <= l && r <= R) return t[x].mx.fi;
pushdown(x);
return max(querymax(L, R, l, mid, ls), querymax(L, R, mid + 1, r, rs));
}
int querymin(int L, int R, int l = 1, int r = n, int x = 1) {
if (r < L || R < l) return inf;
if (L <= l && r <= R) return t[x].mn.fi;
pushdown(x);
return min(querymin(L, R, l, mid, ls), querymin(L, R, mid + 1, r, rs));
}
ll querysum(int L, int R, int l = 1, int r = n, int x = 1) {
if (r < L || R < l) return 0;
if (L <= l && r <= R) return t[x].sum;
pushdown(x);
return querysum(L, R, l, mid, ls) + querysum(L, R, mid + 1, r, rs);
}
void print(int l = 1, int r = n, int x = 1) {
if (l == r) {
cerr << t[x].sum << " ";
return ;
}
pushdown(x);
print(l, mid, ls);
print(mid + 1, r, rs);
}
signed main() {
read(n);
for (int i = 1; i <= n; ++i) read(a[i]);
build();
read(m);
for (int i = 1; i <= m; ++i) {
int op, l, r, x;
read(op, l, r);
if (op <= 3) read(x);
switch (op) {
case 1:
modifyadd(l, r, x);
break;
case 2:
modifymax(l, r, x);
break;
case 3:
modifymin(l, r, x);
break;
case 4:
write(querysum(l, r));
break;
case 5:
write(querymax(l, r));
break;
case 6:
write(querymin(l, r));
break;
}
}
return 0;
}
// 线段树套主席树
#include <bits/stdc++.h>
#define ls(p) t[p].l
#define rs(p) t[p].r
#define lc (x << 1)
#define rc (x << 1 | 1)
#define mid ((l + r) >> 1)
using namespace std;
template <typename Tp> void read(Tp &x) {
x = 0; char ch = getchar(); int f = 0;
while (ch < '0' || ch > '9') { if (ch == '-') f ^= 1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (Tp)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
template <typename Tp, typename... Args>
void read(Tp &t, Args &... args) { read(t); read(args...); }
const int N = 50010;
const int INF = 2147483647;
const int MAX = 1e8;
const int MIN = -1e8;
int n, m, a[N];
struct node {
int l, r, sum;
} t[N * 450];
int rt[N << 2], tot;
int newnode() {
t[++tot] = { 0, 0, 0 };
return tot;
}
void modify(int &p, int val, int cnt, int l = MIN, int r = MAX) {
if (!p) p = newnode();
if (l == r) return t[p].sum += cnt, void();
if (val <= mid) modify(ls(p), val, cnt, l, mid);
else modify(rs(p), val, cnt, mid + 1, r);
t[p].sum = t[ls(p)].sum + t[rs(p)].sum;
}
int query(int p, int L, int R, int l = MIN, int r = MAX) {
if (!p || L > R) return 0;
if (L <= l && r <= R) return t[p].sum;
if (L <= mid && R > mid) return query(ls(p), L, R, l, mid) + query(rs(p), L, R, mid + 1, r);
return (L <= mid) ? query(ls(p), L, R, l, mid) : query(rs(p), L, R, mid + 1, r);
}
void Build(int l = 1, int r = n, int x = 1) {
for (int i = l; i <= r; ++i) modify(rt[x], a[i], 1);
if (l == r) return ;
Build(l, mid, lc);
Build(mid + 1, r, rc);
}
// 返回 [L, R] 中 <= k 的个数
int Rank(int L, int R, int k, int l = 1, int r = n, int x = 1) {
if (L <= l && r <= R) return query(rt[x], 0, k);
int ret = 0;
if (L <= mid) ret = Rank(L, R, k, l, mid, lc);
if (R > mid) ret += Rank(L, R, k, mid + 1, r, rc);
return ret;
}
vector<int> nods;
void work(int L, int R, int l = 1, int r = n, int x = 1) {
if (L <= l && r <= R) return nods.push_back(rt[x]);
if (L <= mid) work(L, R, l, mid, lc);
if (R > mid) work(L, R, mid + 1, r, rc);
}
// 返回 [L, R] 中排名第 k 的数,不合法则 -INF
int Kth(int L, int R, int k) {
if (k <= 0 || k > R - L + 1) return -INF;
nods.clear();
work(L, R);
int l = MIN, r = MAX, cnt;
while (l < r) {
cnt = 0;
for (int i = 0; i < (int)nods.size(); ++i) cnt += t[ls(nods[i])].sum;
if (cnt >= k) {
for (int i = 0; i < (int)nods.size(); ++i) nods[i] = ls(nods[i]);
r = mid;
} else {
for (int i = 0; i < (int)nods.size(); ++i) nods[i] = rs(nods[i]);
l = mid + 1;
k -= cnt;
}
}
return l;
}
void Modify(int pos, int lst, int val, int l = 1, int r = n, int x = 1) {
modify(rt[x], lst, -1);
modify(rt[x], val, 1);
if (l == r) return ;
if (pos <= mid) Modify(pos, lst, val, l, mid, lc);
else Modify(pos, lst, val, mid + 1, r, rc);
}
int main() {
read(n, m);
for (int i = 1; i <= n; ++i) read(a[i]);
Build();
for (int cs = 1; cs <= m; ++cs) {
int op, x, y, z, k;
read(op, x, y);
switch (op) {
case 1:
read(z);
printf("%d\n", Rank(x, y, z - 1) + 1);
break;
case 2:
read(z);
printf("%d\n", Kth(x, y, z));
break;
case 3:
Modify(x, a[x], y); a[x] = y;
break;
case 4:
read(z);
k = Kth(x, y, Rank(x, y, z - 1));
printf("%d\n", k == -INF ? -INF : k);
break;
case 5:
read(z);
k = Kth(x, y, Rank(x, y, z) + 1);
printf("%d\n", k == -INF ? INF : k);
break;
}
}
return 0;
}
/*
1. [l, r] k 排名
找每个区间比 k 小的个数
2. [l, r] 排名为 k
所有区间捞出来,线段树二分?
3. 单点修改下标 pos 的数改为 k
改就是了
4. [l, r] x 的前驱
Kth(Rank(z - 1))
5. [l, r] x 的后继
Kyh(Rank(z) + 1)
*/
// 区间加/乘法
#include <stdio.h>
#include <iostream>
using namespace std;
const int N = 100000;
int n, m;
long long mod;
long long sum[N << 2], mult[N << 2], add[N << 2], a[N];
void pushup(int x);
void pushdown(int x, int l, int r, int m);
void build(int x, int l, int r) {
add[x] = 0; mult[x] = 1;
if (l == r) {
sum[x] = a[l];
return ;
}
int m = (l + r) >> 1;
build(x << 1, l, m);
build(x << 1 | 1, m + 1, r);
pushup(x);
}
void init() {
scanf("%d%d%lld", &n, &m, &mod);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
build(1, 1, n);
}
void pushup(int x) {
sum[x] = (sum[x << 1] + sum[x << 1 | 1]) % mod;
}
void pushdown(int x, int l, int r, int m) {
//left son
sum[x << 1] = (sum[x << 1] * mult[x] + (m - l + 1) * add[x]) % mod;
mult[x << 1] = (mult[x << 1] * mult[x]) % mod;
add[x << 1] = (add[x << 1] * mult[x] + add[x]) % mod;
//right son
sum[x << 1 | 1] = (sum[x << 1 | 1] * mult[x] + (r - m) * add[x]) % mod;
mult[x << 1 | 1] = (mult[x << 1 | 1] * mult[x]) % mod;
add[x << 1 | 1] = (add[x << 1 | 1] * mult[x] + add[x]) % mod;
//clear
add[x] = 0;
mult[x] = 1;
}
void modify(int L, int R, long long val, int x, int l, int r) { //add
if (L <= l && r <= R) {
add[x] = (add[x] + val) % mod;
sum[x] = (sum[x] + val * (long long)(r - l + 1)) % mod;
return ;
}
int m = (l + r) >> 1;
pushdown(x, l, r, m);
if (L <= m)
modify(L, R, val, x << 1, l, m);
if (R > m)
modify(L, R, val, x << 1 | 1, m + 1, r);
pushup(x);
}
void modify1(int L, int R, long long val, int x, int l, int r) { //mult
if (L <= l && r <= R) {
sum[x] = (sum[x] * val) % mod;
add[x] = (add[x] * val) % mod;
mult[x] = (mult[x] * val) % mod;
return ;
}
int m = (l + r) >> 1;
pushdown(x, l, r, m);
if (L <= m)
modify1(L, R, val, x << 1, l, m);
if (R > m)
modify1(L, R, val, x << 1 | 1, m + 1, r);
pushup(x);
}
long long query(int L, int R, int x, int l, int r) {
if (L <= l && r <= R)
return sum[x] % mod;
int m = (l + r) >> 1;
pushdown(x, l, r, m);
long long ret = 0;
if (L <= m)
ret += query(L, R, x << 1, l, m);
if (R > m)
ret += query(L, R, x << 1 | 1, m + 1, r);
return ret % mod;
}
int main() {
init();
while (m--) {
int op, x, y;
long long k;
scanf("%d", &op);
if (op == 1) { //mult
scanf("%d%d%lld", &x, &y, &k);
modify1(x, y, k, 1, 1, n);
}
if (op == 2) { //add
scanf("%d%d%lld", &x, &y, &k);
modify(x, y, k, 1, 1, n);
}
if (op == 3) { //query
scanf("%d%d", &x, &y);
printf("%lld\n", query(x, y, 1, 1, n));
}
}
}
/*
数组实现的普通Treap
2020-6-19
by fxz
*/
#include <bits/stdc++.h>
using namespace std;
struct treap {
private:
// N 为节点数
const static int N = 100010;
const static int INF = 0x7fffffff;
// l,r左右儿子下标 val节点关键码 rnd随机权值 cnt副本数 siz子树大小 tot节点数 root树根
int l[N], r[N], val[N], rnd[N], cnt[N], siz[N], tot, root;
// 回收利用删除节点
int eat[N], et;
//回收节点
void del(int &p) {
eat[++et] = p; p = 0;
}
//开点
int newn(int vl) {
int t = et > 0 ? eat[et--] : ++tot;
val[t] = vl;
rnd[t] = rand();
cnt[t] = siz[t] = 1;
return t;
}
//上载,更新节点
void updata(int p) {
siz[p] = siz[l[p]] + siz[r[p]] + cnt[p];
}
//右旋
void zig(int &p) {
int q = l[p]; l[p] = r[q]; r[q] = p; p = q; updata(r[p]), updata(p);
}
//左旋
void zag(int &p) {
int q = r[p]; r[p] = l[q]; l[q] = p; p = q; updata(l[p]), updata(p);
}
//获取排名
int rank(int vl, int p) {
if (p == 0) return 0;
if (vl == val[p]) return siz[l[p]];
if (vl < val[p]) return rank(vl, l[p]);
return rank(vl, r[p]) + siz[l[p]] + cnt[p];
}
//获取数值
int value(int rk, int p) {
if (p == 0) return INF;
if (siz[p[l]] >= rk) return value(rk, l[p]);
if (siz[p[l]] + cnt[p] >= rk) return val[p];
return value(rk - siz[l[p]] - cnt[p], r[p]);
}
//插入
void _insert(int vl, int &p) {
if (p == 0) {
p = newn(vl);
return ;
}
if (vl == val[p]) {
cnt[p]++; updata(p);
return ;
}
if (vl < val[p]) {
_insert(vl, l[p]);
if (rnd[p] < rnd[l[p]]) zig(p);
} else {
_insert(vl, r[p]);
if (rnd[p] < rnd[r[p]]) zag(p);
}
updata(p);
}
//删除
void _remove(int vl, int &p) {
if (p == 0) return ;
if (vl == val[p]) {
if (cnt[p] > 1) {
cnt[p]--; updata(p);
return ;
}
if (l[p] || r[p]) {
if (r[p] == 0 || rnd[l[p]] > rnd[r[p]]) zig(p), _remove(vl, r[p]);
else zag(p), _remove(vl, l[p]);
updata(p);
} else del(p);
return ;
}
vl < val[p] ? _remove(vl, l[p]) : _remove(vl, r[p]);
updata(p);
}
public:
//重置,初始化
void build() {
tot = et = 0;
newn(-INF), newn(INF);
root = 1, r[1] = 2;
updata(root);
}
//获取某值的排名(定义为比它小的个数+1)
int getrank(int vl) {
return rank(vl, root);
}
//获取排名为rk值
int getval(int rk) {
return value(rk + 1, root);
}
//插入一个值,可重复
void insert(int vl) {
_insert(vl, root);
}
//输出某值前驱,若无则-INF
int getpre(int vl) {
int ret = 1, p = root; // val[1]==-INF
while (p) {
if (vl == val[p]) {
if (l[p] > 0) {
p = l[p];
while (r[p] > 0) p = r[p];
ret = p;
}
}
if (val[p] < vl && val[p] > val[ret]) ret = p;
p = vl < val[p] ? l[p] : r[p];
}
return val[ret];
}
//输出某值后继,若无则INF
int getnxt(int vl) {
int ret = 2, p = root; //val[2]=INF
while (p) {
if (vl == val[p]) {
if (r[p] > 0) {
p = r[p];
while (l[p] > 0) p = l[p];
ret = p;
}
}
if (val[p] > vl && val[p] < val[ret]) ret = p;
p = vl < val[p] ? l[p] : r[p];
}
return val[ret];
}
//删除某值,如果出现多个只删一个
void remove(int vl) {
_remove(vl, root);
}
//返回元素个数,包括重复元素
int size() {
return siz[root] - 2;
}
//判断是否为空
bool empty() {
return size() == 0;
}
} tp;
int n;
int main() {
tp.build();
scanf("%d", &n);
while (n--) {
int op, x;
scanf("%d%d", &op, &x);
switch (op) {
case 1:
tp.insert(x); break;
case 2:
tp.remove(x); break;
case 3:
printf("%d\n", tp.getrank(x)); break;
case 4:
printf("%d\n", tp.getval(x)); break;
case 5:
printf("%d\n", tp.getpre(x)); break;
case 6:
printf("%d\n", tp.getnxt(x)); break;
}
}
}
/*
维护异或和的 01 trie
支持插入,删除,修改,全局+1
*/
#include <bits/stdc++.h>
namespace trie {
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
const int N = 600010;
const int DEP = 22;
int ch[N * DEP][2], w[N * DEP], xorw[N * DEP], sz;
int newnode() {++sz; ch[sz][0] = ch[sz][1] = 0; w[sz] = xorw[sz] = 0; return sz;}
void pushup(int p) {
w[p] = xorw[p] = 0;
if (ls(p)) {
w[p] += w[ls(p)];
xorw[p] ^= xorw[ls(p)] << 1;
}
if (rs(p)) {
w[p] += w[rs(p)];
xorw[p] ^= (xorw[rs(p)] << 1) | (w[rs(p)] & 1);
}
}
void insert(int &p, int x, int d = 0) {
if (!p) p = newnode();
if (d >= DEP) return ++w[p], void();
insert(ch[p][x & 1], x >> 1, d + 1);
pushup(p);
}
void erase(int p, int x, int d = 0) {
if (d >= DEP) return --w[p], void();
erase(ch[p][x & 1], x >> 1, d + 1);
pushup(p);
}
// merge q to p
int merge(int p, int q) {
if (!p || !q) return p + q;
w[p] += w[q]; xorw[p] ^= xorw[q];
ls(p) = merge(ls(p), ls(q));
rs(p) = merge(rs(p), rs(q));
return p;
}
void addall(int p) {
swap(ls(p), rs(p));
if (ls(p)) addall(ls(p));
pushup(p);
}
int xorsum(int p) {return xorw[p];}
}
int main() {
return 0;
}
#include <bits/stdc++.h>
#define il inline
using namespace std;
typedef double db;
const db eps = 1e-8;
il int sign(const db &num) {return (num > eps) - (num < -eps);} // 判断符号,为正则 1 为负则 -1 为零则零
il int cmp(const db &a, const db &b) {return sign(a - b);} // 比较大小
struct vec { // Vector & Point
db x, y;
void input() {scanf("%lf%lf", &x, &y);}
vec(const db &_x = 0, const db &_y = 0): x(_x), y(_y) {}
il vec operator+(const vec &v) const {return vec(x + v.x, y + v.y);}
il vec operator-(const vec &v) const {return vec(x - v.x, y - v.y);}
il vec operator*(const db &a) const {return vec(x * a, y * a);}
il vec operator/(const db &a) const {return vec(x / a, y / a);}
il db len2() const {return x * x + y * y;}
il db len() const {return hypot(x, y);} // 模长
il vec turnc(db r) const {db l = len(); if (!sign(l)) return *this; r /= l; return (*this) * r;} // 改变长度
bool operator<(const vec t) const {return (cmp(x, t.x) == 0) ? (cmp(y, t.y) < 0) : (cmp(x, t.x) < 0);}
bool operator==(const vec t) const {return cmp(x, t.x) == 0 && cmp(y, t.y) == 0;}
};
typedef vec poi;
il db dot(const vec &a, const vec &b) {return a.x * b.x + a.y * b.y;} // 点积
il db crs(const vec &a, const vec &b) {return a.x * b.y - a.y * b.x;} // 叉积
il db dis(const poi &a, const poi &b) {return (b - a).len();} // 两点距离
vector<poi> pts, pois; int n;
poi O;
bool cmpv(poi a, poi b) { // 极角排序(这个 cmp 需要保证所有点在原点一侧)
int k = sign(crs(a - O, b - O));
return (k == 0) ? ((a - O).len2() < (b - O).len2()) : (k > 0);
}
int relat(const poi &a, const poi &b, const poi &c) { // 三点关系,判断是凸还是凹
return sign(crs(b - a, c - b));
}
void Graham(vector<poi> pt, vector<poi> &res) { // Graham 求凸包 (极角排序+单调栈)
res.clear();
for (int i = 1; i < (int)pt.size(); ++i) if (pt[i] < pt[0]) swap(pt[i], pt[0]);
O = pt[0];
sort(pt.begin() + 1, pt.end(), cmpv);
for (int i = 0; i < (int)pt.size(); ++i) {
while (res.size() >= 2 && relat(res[res.size() - 2], res[res.size() - 1], pt[i]) <= 0) res.pop_back();
res.push_back(pt[i]);
}
}
db Aera(vec a, vec b, vec c) {return abs(crs(b - a, c - a));} // 三角形面积 |(*2)|
db Diam(vector<poi> pt) { // 凸包直径 Diameter “旋转卡壳”
int n = pt.size(), j = 0; db res = 0;
if (pt.size() == 2) return (pt[0] - pt[1]).len2();
pt.push_back(pt[0]);
for (int i = 0; i < n; ++i) {
while (Aera(pt[i], pt[i + 1], pt[(j + 1) % n]) >= Aera(pt[i], pt[i + 1], pt[j])) j = (j + 1) % n;
res = max(res, max((pt[j] - pt[i]).len2(), (pt[j] - pt[i + 1]).len2()));
}
return res;
}
db Perim(vector<poi> pt) { // 凸包周长 Perimeter
db res = 0; int n = pois.size();
for (int i = 0; i < n; ++i) res += dis(pois[(i == 0) ? (n - 1) : (i - 1)], pois[i]);
return res;
}
db Area(const vector<poi> &pts) { // 任意多边形面积 (有向面积:顺负逆正)
db res = 0; int n = pts.size();
for (int i = 1; i < n - 1; ++i) res += crs(pts[i] - pts[0], pts[i + 1] - pts[0]);
return res / 2.0;
}
poi Grav(const vector<poi> &pts) { // Center of Gravity 多边形质心
poi g; db sumarea = 0; int n = pts.size();
for (int i = 2; i < n; ++i) {
db S = crs(pts[i - 1] - pts[0], pts[i] - pts[0]);
g = g + (pts[0] + pts[i - 1] + pts[i]) * S;
sumarea += S;
}
return g / (sumarea * 3);
}
int main() {
// Readin
scanf("%d", &n); pts.resize(n);
for (int i = 0; i < n; ++i) pts[i].input();
}
/*
半平面交
本代码 --> 求凸多边形面积并
*/
#include <bits/stdc++.h>
#define il inline
using namespace std;
typedef double db;
const db Pi = acos(-1.0);
const db eps = 1e-7;
il int sign(db num) {return (num > eps) - (num < -eps);}
il int cmp(db a, db b) {return sign(a - b);}
struct vec {
db x, y;
vec(db _x = 0, db _y = 0): x(_x), y(_y) {}
il void input() {scanf("%lf%lf", &x, &y);}
il vec operator+(const vec &t) const {return vec(x + t.x, y + t.y);}
il vec operator-(const vec &t) const {return vec(x - t.x, y - t.y);}
il vec operator*(const db &t) const {return vec(x * t, y * t);}
il vec operator/(const db &t) const {return vec(x / t, y / t);}
il db len2() const {return x * x + y * y;}
il db len() const {return hypot(x, y);}
bool operator<(const vec &t) const {return (cmp(x, t.x) == 0) ? (cmp(y, t.y) < 0) : (cmp(x, t.x) < 0);}
};
typedef vec poi;
il db dot(const vec &a, const vec &b) {return a.x * b.x + a.y * b.y;}
il db crs(const vec &a, const vec &b) {return a.x * b.y - a.y * b.x;}
il db dis(const vec &a, const vec &b) {return (a - b).len();}
struct lin {
poi s, e; db k;
lin(poi _s, vec _e): s(_s), e(_e), k(atan2((e - s).y, (e - s).x)) {}
il poi operator()() const {return e - s;}
};
il poi cross(const lin &l1, const lin &l2) {return l1.s + l1() * crs(l2.s - l1.s, l2()) / crs(l1(), l2());}
vector<lin> L; // 半平面们,统一向量左侧为半平面
vector<poi> P, pts; // 多边形们
int n, m;
bool cmpl(lin a, lin b) { // 极角排序,极角相同靠左优先
if (cmp(a.k, b.k) == 0) return sign(crs(b.e-a.s, a())) > 0;
return cmp(a.k, b.k) < 0;
}
bool Onright(lin a, lin b, lin c) { // a,b 交点在 c 右边
poi p = cross(a, b);
return sign(crs(c(), p - c.s)) <= 0;
}
void Halfplane(vector<lin> Ls, vector<poi> &res) { // 半平面交
res.clear();
sort(Ls.begin(), Ls.end(), cmpl);
deque<int> q;
for (int i = 0; i < (int)Ls.size(); ++i) {
if (i != 0 && cmp(Ls[i].k, Ls[i - 1].k) == 0) continue;
while (q.size() >= 2 && Onright(Ls[q[q.size() - 2]], Ls[q.back()], Ls[i])) q.pop_back();
while (q.size() >= 2 && Onright(Ls[q.front()], Ls[q[1]], Ls[i])) q.pop_front();
q.push_back(i);
}
while (q.size() >= 2 && Onright(Ls[q[q.size() - 2]], Ls[q.back()], Ls[q.front()])) q.pop_back();
while (q.size() >= 2 && Onright(Ls[q[0]], Ls[q[1]], Ls[q.back()])) q.pop_front();
if (q.size() >= 2) res.push_back(cross(Ls[q.back()], Ls[q.front()]));
while (q.size() >= 2) {
res.push_back(cross(Ls[q[0]], Ls[q[1]]));
q.pop_front();
}
}
db Area(const vector<poi> &pts) { //多边形面积
db res = 0;
for (int i = 1; i < (int)pts.size() - 1; ++i) res += crs(pts[i] - pts[0], pts[i + 1] - pts[0]);
return res / 2.0;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &m);
pts.resize(m);
for (int i = 0; i < m; ++i) pts[i].input();
for (int i = 0; i < m; ++i) L.push_back(lin(pts[i], pts[(i + 1) % m]));
}
Halfplane(L, P);
db ans = Area(P);
printf("%.3lf\n", ans);
return 0;
}
/*
https://vjudge.net/problem/UVA-12304
计算几何 基du础liu题 点线圆相关
计算几何板子 v1.0
*/
#include <bits/stdc++.h>
#define il inline
using namespace std;
typedef double db;
const db eps = 1e-10;
il int sign(const db &num) {return (num > eps) - (num < -eps);} // 判断符号,为正则 1 为负则 -1 为零则零
il int cmp(const db &a, const db &b) {return sign(a - b);} // 比较大小
const db Pi = acos(-1);
il db R_to_D(const db &rad) {return 180.0 / Pi * rad;}
il db D_to_R(const db °) {return Pi / 180.0 * deg;}
struct vec { // Vector & Point
db x, y;
void input() {scanf("%lf%lf", &x, &y);}
vec(const db &_x = 0, const db &_y = 0): x(_x), y(_y) {}
il vec operator+(const vec &v) const {return vec(x + v.x, y + v.y);}
il vec operator-(const vec &v) const {return vec(x - v.x, y - v.y);}
il vec operator*(const db &a) const {return vec(x * a, y * a);}
il vec operator/(const db &a) const {return vec(x / a, y / a);}
il db len2() const {return x * x + y * y;}
il db len() const {return hypot(x, y);} // 模长
il vec unit() const {db l = len(); return (sign(l) == 0) ? (vec(0, 0)) : (*this / l); } // 单位化
il vec turnc(db r) const {db l = len(); if (!sign(l)) return *this; r /= l; return (*this) * r;} // 改变长度
il db angle() const { db k = atan2(y, x); if (sign(k) < 0) k += Pi; if (cmp(k, Pi) == 0) k -= Pi; return k;}
bool operator<(const vec t) const {return (cmp(x, t.x) == 0) ? (cmp(y, t.y) < 0) : (cmp(x, t.x) < 0);}
bool operator==(const vec t) const {return cmp(x, t.x) == 0 && cmp(y, t.y) == 0;}
};
typedef vec poi;
struct cir { // Circle
poi O; db r;
cir() {}
cir(const poi &_O, const db &_r): O(_O), r(_r) {}
void input() {O.input(); scanf("%lf", &r);}
};
struct lin { // Line & Ray
poi p; vec v;
lin() {}
lin(const poi &_p, const vec &_v): p(_p), v(_v) {} // 直线上点p,方向向量v
lin(const db &_x1, const db &_y1, const db &_x2, const db &_y2): p(_x1, _y1), v(_x2 - _x1,
_y2 - _y1) {} // 直线上两点
il db angle() const {return v.angle();}
void input() {p.input(); v.input(); v = v - p;}
};
typedef lin ray;
il db dot(const vec &a, const vec &b) {return a.x * b.x + a.y * b.y;} // 点积
il db crs(const vec &a, const vec &b) {return a.x * b.y - a.y * b.x;} // 叉积
il vec rot90(const vec &t) {return vec(-t.y, t.x);} // +90
il vec rotn90(const vec &t) {return vec(t.y, -t.x);} // -90
il vec rot180(const vec &t) {return vec(-t.x, -t.y);} // +180
il poi cross(const lin &a, const lin &b) {return a.p + a.v * crs((b.p - a.p), b.v) / crs(a.v, b.v);} // 求两直线交点
il poi foot(const lin &l, const poi &p) {return cross(lin(p, rot90(l.v)), l);} // p 到 l 的垂足
il db dist(const lin &l, const poi &p) {return (p - foot(l, p)).len();} // 点到直线距离
il db Helen(const db &a, const db &b, const db &c) { db p = (a + b + c) / 2; return sqrt(p * (p - a) * (p - b) * (p - c));} // 海伦公式,求三角形面积
il int rela(const cir &c, const poi &p) {return cmp((c.O - p).len(), c.r) + 1;} // 点与圆关系,0:点在圆内;1:点在圆上;2:点在圆外
il int rela(const cir &c, const lin &l); // 圆与直线关系
il int rela(const cir &c, const lin &l); // 圆与圆关系
il void cross(const cir &c, const lin &l, poi &p1, poi &p2); // 圆与直线交点
void ptv(const vec &v) {printf(">>> [%.6lf,%.6lf]\n", v.x, v.y);}
void ptp(const poi &p) {printf(">>> (%.6lf,%.6lf)\n", p.x, p.y);}
void ptl(const lin &l) {printf(">>> (%.6lf,%.6lf) [%.6lf,%.6lf]\n", l.p.x, l.p.y, l.v.x, l.v.y);}
void ptc(const cir &c) {printf(">>> (%.6lf,%.6lf) r=%0.6lf\n", c.O.x, c.O.y, c.r);}
void ptt(const db &t) {printf(">>> %.6lf\n", t);}
cir OutsideCircle(const poi &A, const poi &B, const poi &C) { // 外接圆
poi O = cross(lin((A + B) / 2, rot90(B - A)), lin((A + C) / 2, rot90(A - C)));
return cir(O, (O - A).len());
}
cir InsideCircle(const poi &A, const poi &B, const poi &C) { // 内切圆
vec a = C - B, c = A - B, b = C - A;
db p = a.len() + b.len() + c.len();
db r = abs(crs(a, c) / p);
poi O = (A * a.len() + B * b.len() + C * c.len()) / p;
return cir(O, r);
}
void TangentLine(const cir &C, const poi &P, vector<lin> &res) { // 过点 P 到圆的切线
res.clear();
int op = cmp((C.O - P).len(), C.r);
if (op < 0) return ; // P 在圆内无切线
if (op == 0) {
res.push_back(lin(P, rot90(C.O - P))); // P 在圆上切线与半径垂直
return ;
}
// P 在圆外两切线
vec d = P - C.O;
db t = sqrt(d.len2() - C.r * C.r);
db h = t * C.r / d.len(), x = C.r * h / t;
poi F = C.O + d.turnc(x);
res.push_back(lin(P, (F + rot90(d).turnc(h) - P)));
res.push_back(lin(P, (F + rotn90(d).turnc(h) - P)));
}
void GetCircle(const poi &P, const lin &l, const db &r,
vector<poi> &res) { // 给圆上一点,一切线,半径:求圆心
res.clear();
if (sign(crs(l.v, l.p - P)) == 0) { // P 在 l 上,P 为切点
res.push_back(P + rot90(l.v).turnc(r));
res.push_back(P + rotn90(l.v).turnc(r));
return ;
}
poi F = foot(l, P); // F 为 P 到 l 垂足
int op = cmp((P - F).len(), 2 * r);
if (op > 0) return ; // P 到 l 距离大于 2r
if (op == 0) { // P 到 l 距离等于 2r,PF为直径
res.push_back((P + F) / 2);
return ;
}
db t = (P - F).len() - r, d = sqrt(r * r - t * t);
res.push_back(F + l.v.turnc(d) + (P - F).turnc(r));
res.push_back(F - l.v.turnc(d) + (P - F).turnc(r));
}
void GetCircle(const lin &l1, const lin &l2, const db &r, vector<poi> &res) { // 两切线+半径:求圆心
res.clear();
lin l1u = lin(l1.p + rot90(l1.v).turnc(r), l1.v), l1d = lin(l1.p + rotn90(l1.v).turnc(r), l1.v);
lin l2u = lin(l2.p + rot90(l2.v).turnc(r), l2.v), l2d = lin(l2.p + rotn90(l2.v).turnc(r), l2.v);
res.push_back(cross(l1u, l2u)); res.push_back(cross(l1u, l2d));
res.push_back(cross(l1d, l2u)); res.push_back(cross(l1d, l2d));
}
void CircleCross(const cir &c1, const cir &c2, vector<poi> &res) { // 求两圆交点
res.clear();
vec d = c2.O - c1.O;
int op = cmp(c1.r + c2.r, d.len());
if (op < 0) return ;
if (op == 0) {
res.push_back(c1.O + d.turnc(c1.r));
return ;
}
db t = c1.r * (c1.r * c1.r + d.len2() - c2.r * c2.r) / (2.0 * c1.r * d.len());
db h = sqrt(c1.r * c1.r - t * t);
res.push_back(c1.O + rot90(d).turnc(h) + d.turnc(t));
res.push_back(c1.O + rotn90(d).turnc(h) + d.turnc(t));
}
void TangentCircle(const cir &c1, const cir &c2, const db &r,
vector<poi> &res) { // 给两无交圆 ,求半径为r的切圆
CircleCross(cir(c1.O, c1.r + r), cir(c2.O, c2.r + r), res);
}
void output(vector<poi> &pois) {
sort(pois.begin(), pois.end());
printf("[");
for (int i = 0; i < (int)pois.size(); ++i) {
printf("(%.6lf,%.6lf)", pois[i].x, pois[i].y);
if (i < (int)pois.size() - 1) putchar(',');
}
printf("]\n");
}
void output(vector<db> &nums) {
sort(nums.begin(), nums.end());
printf("[");
for (int i = 0; i < (int)nums.size(); ++i) {
printf("%.6lf", nums[i]);
if (i < (int)nums.size() - 1) putchar(',');
}
printf("]\n");
}
string opt;
int main() {
while (cin >> opt) {
if (opt == "CircumscribedCircle") {
poi A, B, C; A.input(); B.input(); C.input();
cir c = OutsideCircle(A, B, C);
printf("(%.6lf,%.6lf,%.6lf)\n", c.O.x, c.O.y, c.r);
} else if (opt == "InscribedCircle") {
poi A, B, C; A.input(); B.input(); C.input();
cir c = InsideCircle(A, B, C);
printf("(%.6lf,%.6lf,%.6lf)\n", c.O.x, c.O.y, c.r);
} else if (opt == "TangentLineThroughPoint") {
vector<lin> lins; vector<db> degs; poi P; cir c;
c.input(); P.input();
TangentLine(c, P, lins);
for (int i = 0; i < (int)lins.size(); ++i)
degs.push_back(R_to_D(lins[i].angle()));
output(degs);
} else if (opt == "CircleThroughAPointAndTangentToALineWithRadius") {
vector<poi> pois; poi P; lin l0; db r;
P.input(); l0.input(); scanf("%lf", &r);
GetCircle(P, l0, r, pois);
output(pois);
} else if (opt == "CircleTangentToTwoLinesWithRadius") {
vector<poi> pois; lin l1, l2; db r;
l1.input(); l2.input(); scanf("%lf", &r);
GetCircle(l1, l2, r, pois);
output(pois);
} else if (opt == "CircleTangentToTwoDisjointCirclesWithRadius") {
vector<poi> pois; cir c1, c2; db r;
c1.input(); c2.input(); scanf("%lf", &r);
TangentCircle(c1, c2, r, pois);
output(pois);
}
}
}
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;
typedef long double db;
const int N = 100010;
struct vec {
db x, y;
vec(const db &_x = 0, const db &_y = 0): x(_x), y(_y) {}
vec operator+(const vec &t) const {return vec(x + t.x, y + t.y);}
vec operator-(const vec &t) const {return vec(x - t.x, y - t.y);}
vec operator*(const db &t) const {return vec(x * t, y * t);}
vec operator/(const db &t) const {return vec(x / t, y / t);}
const db len2() const {return x * x + y * y;}
const db len() const {return sqrt(len2());}
};
db dot(const vec &a, const vec &b) {return a.x * b.x + a.y * b.y;}
db crs(const vec &a, const vec &b) {return a.x * b.y - a.y * b.x;}
vec pt[N]; int n;
vec rot90(vec a) {return vec(a.y, -a.x);}
vec cross(vec p1, vec v1, vec p2, vec v2) {return p1 + v1 * crs(p2 - p1, v2) / crs(v1, v2);}
vec get_circle(vec a, vec b, vec c) { return cross((a + b) / 2, rot90(b - a), (b + c) / 2, rot90(c - b));}
void min_circle_cover(vec p[], int t) {
random_shuffle(p + 1, p + n + 1);
db r_2 = 0; vec O;
for (int i = 1; i <= n; ++i) {
if ((p[i] - O).len2() > r_2) {
O = p[i], r_2 = 0;
for (int j = 1; j < i; ++j) {
if ((p[j] - O).len2() > r_2) {
O = (p[i] + p[j]) / 2, r_2 = (p[i] - O).len2();
for (int k = 1; k < j; ++k) {
if ((p[k] - O).len2() > r_2) {
O = get_circle(p[i], p[j], p[k]); r_2 = (p[k] - O).len2();
}
}
}
}
}
}
printf("%.10Lf\n%.10Lf %.10Lf\n", sqrt(r_2), O.x, O.y);
}
int main() {
srand(time(0));
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%Lf%Lf", &pt[i].x, &pt[i].y);
min_circle_cover(pt, n);
}
#include <bits/stdc++.h>
using namespace std;
const int N = 2000100;
int n, m;
struct twosat {
int head[N], pnt[N], nxt[N], E;
int dfn[N], low[N], tis, st[N], top, col[N], co, ans[N];
void add(int u, int v) {
E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E;
}
void tarjan(int u) {
st[++top] = u; dfn[u] = low[u] = ++tis;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if (!col[v]) low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
col[u] = ++co;
while (st[top] != u) {col[st[top]] = co; top--;}
top--;
}
}
bool solve() {
for (int i = 1; i <= 2 * n; i++) if (!dfn[i]) tarjan(i);
for (int i = 1; i <= n; i++) {
if (col[i] == col[i + n]) return 0;
ans[i] = (col[i] > col[i + n]);
}
return 1;
}
void insert(int i, bool a, int j, bool b) {
// here xi=a or xj=b
add(i + n * (a ^ 1), j + b * n);
add(j + n * (b ^ 1), i + a * n);
// other forms
// if xi=a then xj=b
// add(i+a*n,j+b*n);
// add(j+(b^1)*n,i+(a^1)*n);
}
} S;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, a, v, b;
scanf("%d%d%d%d", &u, &a, &v, &b);
S.insert(u, a, v, b);
}
bool fg = S.solve();
if (!fg) printf("IMPOSSIBLE\n");
else {
printf("POSSIBLE\n");
for (int i = 1; i <= n; i++) printf("%d ", S.ans[i]);
printf("\n");
}
}
#include <bits/stdc++.h>
using namespace std;
template<typename T>
inline void red(T &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<size_t N, size_t M>
struct Dinic {
const int inf = 0x3f3f3f3f;
int fl[M << 1], pnt[M << 1], nxt[M << 1], cur[N], head[N], dep[N], E, S, T;
long long maxf;
Dinic() {memset(head, -1, sizeof(head)); E = -1;}
void adde(int u, int v, int c) {
E++; pnt[E] = v; fl[E] = c; nxt[E] = head[u]; head[u] = E;
E++; pnt[E] = u; fl[E] = 0; nxt[E] = head[v]; head[v] = E;
}
bool BFS(int u) {
memset(dep, 0x3f, sizeof(dep)); dep[S] = 0;
queue<int> q; q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
if (u == T) break;
for (int i = head[u]; i != -1; i = nxt[i]) {
if (fl[i] > 0 && dep[pnt[i]] == inf)
dep[pnt[i]] = dep[u] + 1, q.push(pnt[i]);
}
}
return dep[T] != inf;
}
int DFS(int u, int nf) {
if (u == T || nf == 0) return nf;
int flow = 0, tf;
for (int &i = cur[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (dep[v] != dep[u] + 1) continue;
tf = DFS(v, min(nf, fl[i]));
if (tf == 0) continue;
flow += tf; nf -= tf;
fl[i] -= tf; fl[i ^ 1] += tf;
if (nf == 0) break;
}
return flow;
}
long long maxflow() {
maxf = 0;
while (BFS(S)) {
memcpy(cur, head, sizeof(cur));
maxf += DFS(S, inf);
}
return maxf;
}
};
Dinic<205, 5005> G;
int n, m, s, t;
int main() {
// scanf("%d%d%d%d",&n,&m,&s,&t);
red(n); red(m); red(s); red(t);
G.S = s, G.T = t;
for (int i = 1; i <= m; ++i) {
int u, v, c; red(u); red(v); red(c);
// scanf("%d%d%d",&u,&v,&c);
G.adde(u, v, c);
}
printf("%lld\n", G.maxflow());
}
// 割边(桥)
#include <bits/stdc++.h>
using namespace std;
const int N = 20010;
const int M = 200010;
int head[N], pnt[M], nxt[M], E, n, m;
int dfn[N], low[N], tim;
bool ecut[M];
void adde(int u, int v) {
E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E;
}
void tarjan(int u, int in_edge) { // 考虑重边
dfn[u] = low[u] = ++tim;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!dfn[v]) {
tarjan(v, i);
low[u] = min(low[u], low[v]);
if (dfn[u] < low[v]) ecut[i] = ecut[i ^ 1] = true;
} else if (in_edge != (i ^ 1)) low[u] = min(low[u], dfn[v]);
}
}
int main() {
scanf("%d%d", &n, &m);
E = 1;
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
adde(u, v); adde(v, u);
}
for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i, 0);
return 0;
}
// 边双连通分量 & 缩点
#include <bits/stdc++.h>
using namespace std;
const int N = 20010;
const int M = 200010;
int head[N], pnt[M], nxt[M], E, n, m;
int headc[N], pntc[M], nxtc[M], Ec;
int dfn[N], low[N], tim;
bool ecut[M];
void adde(int u, int v) {
E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E;
}
void addec(int u, int v) {
Ec++; pntc[Ec] = v; nxtc[Ec] = headc[u]; headc[u] = Ec;
}
void tarjan(int u, int in_edge) { // 考虑重边
dfn[u] = low[u] = ++tim;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!dfn[v]) {
tarjan(v, i);
low[u] = min(low[u], low[v]);
if (dfn[u] < low[v]) ecut[i] = ecut[i ^ 1] = true;
} else if (in_edge != (i ^ 1)) low[u] = min(low[u], dfn[v]);
}
}
int col[N], dcc;
void dfs(int u) {
col[u] = dcc;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (col[v] || ecut[i]) continue;
dfs(v);
}
}
int main() {
scanf("%d%d", &n, &m);
E = 1; // !!
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
adde(u, v); adde(v, u);
}
// e-cut
for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i, 0);
// e-DCC 断开割边,每个联通块即 e-DCC
for (int i = 1; i <= n; ++i) if (!col[i]) {
++dcc, dfs(i);
}
// e-DCC 缩点
for (int i = 2; i <= E; ++i) {
int u = pnt[i], v = pnt[i ^ 1];
if (col[u] == col[v]) continue;
addec(col[u], col[v]);
}
return 0;
}
// 最小割树
#include <bits/stdc++.h>
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
using namespace std;
const int N = 505;
const int M = 3005;
const int inf = 0x3f3f3f3f;
int n, m, q;
struct networkflow {
int head[N], pnt[M << 1], nxt[M << 1], fl[M << 1], E;
int dep[N], cur[N], maxf;
void adde(int u, int v, int f) {
E++; pnt[E] = v; fl[E] = f; nxt[E] = head[u]; head[u] = E;
E++; pnt[E] = u; fl[E] = 0; nxt[E] = head[v]; head[v] = E;
}
void init() {
memset(head, -1, sizeof(head));
E = -1;
}
void reset() { for (int i = 0; i < E; i += 2) fl[i] += fl[i + 1], fl[i + 1] = 0;}
bool BFS(int S, int T) {
memset(dep, 0x3f, sizeof(dep));
dep[S] = 0; queue<int> q; q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (fl[i] > 0 && dep[v] == inf) {dep[v] = dep[u] + 1; q.push(v);}
}
}
return dep[T] < inf;
}
int DFS(int u, int T, int nf) {
if (u == T || nf == 0) return nf;
int flow = 0, tf;
for (int &i = cur[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (dep[v] == dep[u] + 1) {
tf = DFS(v, T, min(nf, fl[i]));
flow += tf; nf -= tf;
fl[i] -= tf; fl[i ^ 1] += tf;
if (nf == 0) break;
}
}
return flow;
}
void Dinic(int S, int T) {
maxf = 0;
while (BFS(S, T)) {
memcpy(cur, head, sizeof(head));
maxf += DFS(S, T, inf);
}
}
} G;
int t[N], head[N], pnt[N << 1], nxt[N << 1], wth[N << 1], E;
int tl[N], tr[N];
void adde(int u, int v, int w) {
// fprintf(stderr,"e : %d %d %d\n",u,v,w);
E++; pnt[E] = v; wth[E] = w; nxt[E] = head[u]; head[u] = E;
}
void Build(int l, int r) {
if (l == r) return ;
G.reset(); G.Dinic(t[l], t[r]);
adde(t[l], t[r], G.maxf); adde(t[r], t[l], G.maxf);
int cl = 0, cr = 0;
for (int i = l; i <= r; ++i) {
if (G.dep[t[i]] == inf) tr[cr++] = t[i];
else tl[cl++] = t[i];
}
for (int i = 0; i < cl; ++i) t[l + i] = tl[i];
for (int i = 0; i < cr; ++i) t[l + cl + i] = tr[i];
Build(l, l + cl - 1); Build(l + cl, l + cl + cr - 1);
}
int fa[10][N], mn[10][N], dep[N];
bool vis[N];
void Prework(int u) {
vis[u] = 1;
for (int i = 1; i < 10; ++i) {
fa[i][u] = fa[i - 1][fa[i - 1][u]];
if (fa[i][u] == 0) break;
mn[i][u] = min(mn[i - 1][u], mn[i - 1][fa[i - 1][u]]);
}
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == fa[0][u]) continue;
fa[0][v] = u; mn[0][v] = wth[i]; dep[v] = dep[u] + 1;
Prework(v);
}
}
int Query(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
int d = dep[u] - dep[v], ret = inf;
for (int i = 0; i < 10; ++i) if ((d >> i) & 1)
ret = min(ret, mn[i][u]), u = fa[i][u];
if (u == v) return ret;
for (int i = 9; i >= 0; --i) if (fa[i][u] != fa[i][v])
ret = min(ret, min(mn[i][u], mn[i][v])),
u = fa[i][u], v = fa[i][v];
return min(ret, min(mn[0][u], mn[0][v]));
}
int main() {
red(n); red(m);
G.init();
for (int i = 1; i <= m; ++i) {
int u, v, w; red(u); red(v); red(w);
G.adde(u, v, w); G.adde(v, u, w);
}
for (int i = 1; i <= n; ++i) t[i] = i;
Build(1, n);
Prework(1);
red(q);
while (q--) {
int u, v; red(u); red(v);
printf("%d\n", Query(u, v));
}
}
// 二分图最大匹配 匈牙利算法
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
vector<int> e[N];
int mx[N], my[N], n, m, E;
bool vis[N];
bool find(int x) {
for (auto y : e[x]) if (!vis[y]) {
vis[y] = 1;
if (my[y] == 0 || find(my[y])) {
my[y] = x, mx[x] = y;
return true;
}
}
return false;
}
int march(){
int cnt = 0;
memset(my, 0, sizeof(my));
memset(mx, 0, sizeof(mx));
for (int i = 1; i <= n; ++i) {
memset(vis, 0, sizeof(vis));
cnt += find(i);
}
return cnt;
}
int main() {
scanf("%d%d%d", &n, &m, &E);
for (int i = 1; i <= E; ++i) {
int u, v; scanf("%d%d", &u, &v);
e[u].push_back(v);
}
printf("%d\n", march());
}
#include <bits/stdc++.h>
#define fi first
#define se second
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp> bool umax(_Tp &x, _Tp y) {return (x < y) ? (x = y, true) : (false);}
template<typename _Tp> bool umin(_Tp &x, _Tp y) {return (x > y) ? (x = y, true) : (false);}
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
int n, m, s, t;
struct networkflow {
static const int N = 5010, M = 100010;
int head[N], pnt[M], fl[M], nxt[M], cst[M], pre[N], lst[N], E = -1;
int dis[N], h[N]; bool vis[N];
int minc, maxf, n;
void init(int _n) {
memset(head, -1, sizeof(head)); E = -1; n = _n;
}
void adde(int u, int v, int f, int c) {
++E; pnt[E] = v; nxt[E] = head[u]; head[u] = E; fl[E] = f; cst[E] = c;
++E; pnt[E] = u; nxt[E] = head[v]; head[v] = E; fl[E] = 0; cst[E] = -c;
}
bool SPFA(int S, int T) {
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[S] = 0; vis[S] = 1; queue<int> q; q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
vis[u] = 0;
for (int i = head[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (fl[i] > 0 && dis[u] + cst[i] < dis[v]) {
dis[v] = dis[u] + cst[i]; pre[v] = u; lst[v] = i;
if (!vis[v]) q.push(v), vis[v] = 1;
}
}
}
return dis[T] < inf;
}
void work(int S, int T) {
for (int i = 0; i <= n; ++i) h[i] += dis[i];
int flow = inf;
for (int u = T; u != S; u = pre[u]) flow = min(flow, fl[lst[u]]);
maxf += flow; minc += flow * h[T];
for (int u = T; u != S; u = pre[u]) {
fl[lst[u]] -= flow;
fl[lst[u] ^ 1] += flow;
}
}
bool Dij(int S, int T) {
priority_queue<P, vector<P>, greater<P> > q;
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[S] = 0; q.push({0, S});
while (!q.empty()) {
int u = q.top().se; q.pop();
if (vis[u]) continue; vis[u] = 1;
for (int i = head[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (fl[i] > 0 && dis[v] > dis[u] + cst[i] + h[u] - h[v]) {
dis[v] = dis[u] + cst[i] + h[u] - h[v];
pre[v] = u; lst[v] = i;
q.push({dis[v], v});
}
}
}
return dis[T] < inf;
}
void MFMC(int S, int T) {
minc = maxf = 0;
memset(h, 0, sizeof(h));
if (SPFA(S, T)) work(S, T);
else return ;
while (Dij(S, T)) work(S, T);
}
} G;
int main() {
red(n); red(m); red(s); red(t);
G.init(n);
for (int i = 1; i <= m; ++i) {
int a, b, c, d; red(a); red(b); red(c); red(d);
G.adde(a, b, c, d);
}
G.MFMC(s, t);
printf("%d %d\n", G.maxf, G.minc);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
template<size_t N, size_t M>
struct SPFA_Dinic {
const int inf = 0x3f3f3f3f;
int fl[M << 1], cst[M << 1], pnt[M << 1], nxt[M << 1], cur[N], head[N], dis[N], E, S, T;
bool vis[N];
int maxf, minc;
SPFA_Dinic() {memset(head, -1, sizeof(head)); E = -1;}
void adde(int u, int v, int c, int w) { // (u,v) c容量限制,w单位费用
E++; pnt[E] = v; fl[E] = c; cst[E] = w; nxt[E] = head[u]; head[u] = E;
E++; pnt[E] = u; fl[E] = 0; cst[E] = -w; nxt[E] = head[v]; head[v] = E;
}
bool SPFA() {
memset(dis, 0x3f, sizeof(dis));
queue<int> q; q.push(S);
dis[S] = 0; vis[S] = 1;
while (!q.empty()) {
int u = q.front(); q.pop(); vis[u] = 0;
for (int i = head[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (fl[i] > 0 && dis[v] > dis[u] + cst[i]) {
dis[v] = dis[u] + cst[i];
if (!vis[v]) q.push(v), vis[v] = 1;
}
}
}
return dis[T] != inf;
}
int DFS(int u, int nf) {
if (u == T || nf == 0) return nf;
int flow = 0, tf; vis[u] = 1;
for (int &i = cur[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (!vis[v] && fl[i] && dis[v] == dis[u] + cst[i]) {
tf = DFS(v, min(nf, fl[i]));
if (tf) {flow += tf; nf -= tf; fl[i] -= tf; fl[i ^ 1] += tf; minc += tf * cst[i];}
}
if (nf == 0) break;
}
vis[u] = 0;
return flow;
}
void MFMC() {
maxf = minc = 0;
int cnt = 0;
while (SPFA()) {
memcpy(cur, head, sizeof(cur));
maxf += DFS(S, inf);
}
}
};
SPFA_Dinic<5005, 50005> G;
int n, m, s, t;
int main() {
scanf("%d%d%d%d", &n, &m, &s, &t);
G.S = s, G.T = t;
for (int i = 1; i <= m; ++i) {
int u, v, c, w;
scanf("%d%d%d%d", &u, &v, &c, &w);
G.adde(u, v, c, w);
}
G.MFMC();
printf("%d %d\n", G.maxf, G.minc);
return 0;
}
#include <bits/stdc++.h>
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, s, t;
struct networkflow {
static const int N = 5010, M = 100010;
int head[N], pnt[M], fl[M], nxt[M], cst[M], pre[N], lst[N], E = -1;
int dis[N]; bool vis[N];
int minc, maxf;
void init() {
memset(head, -1, sizeof(head)); E = -1;
}
void adde(int u, int v, int f, int c) {
++E; pnt[E] = v; nxt[E] = head[u]; head[u] = E; fl[E] = f; cst[E] = c;
++E; pnt[E] = u; nxt[E] = head[v]; head[v] = E; fl[E] = 0; cst[E] = -c;
}
bool SPFA(int S, int T) {
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[S] = 0; vis[S] = 1; queue<int> q; q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
vis[u] = 0;
for (int i = head[u]; i != -1; i = nxt[i]) {
int v = pnt[i];
if (fl[i] > 0 && dis[u] + cst[i] < dis[v]) {
dis[v] = dis[u] + cst[i]; pre[v] = u; lst[v] = i;
if (!vis[v]) q.push(v), vis[v] = 1;
}
}
}
return dis[T] < inf;
}
void work(int S, int T) {
int flow = inf;
for (int u = T; u != S; u = pre[u]) flow = min(flow, fl[lst[u]]);
maxf += flow; minc += flow * dis[T];
for (int u = T; u != S; u = pre[u]) {
fl[lst[u]] -= flow;
fl[lst[u] ^ 1] += flow;
}
}
void MFMC(int S, int T) {
minc = maxf = 0;
while (SPFA(S, T)) work(S, T);
}
} G;
int main() {
red(n); red(m); red(s); red(t);
G.init();
for (int i = 1; i <= m; ++i) {
int a, b, c, d; red(a); red(b); red(c); red(d);
G.adde(a, b, c, d);
}
G.MFMC(s, t);
printf("%d %d\n", G.maxf, G.minc);
}
// Prufer 序列
#include <bits/stdc++.h>
template <typename Tp>
inline void read(Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
using namespace std;
const int N = 5000010;
int n, type, a[N];
long long ans = 0;
namespace prufer {
int p[N], f[N], deg[N];
void encode(int *f, int n) { // father -> prufer
for (int i = 1; i <= n; ++i) deg[i] = 0;
for (int i = 1; i < n; ++i) ++deg[f[i]];
for (int i = 1, j = 1; i <= n - 2; ++i, ++j) {
while (deg[j]) ++j; p[i] = f[j];
while (i <= n - 2 && --deg[p[i]] == 0 && p[i] < j) p[i + 1] = f[p[i]], ++i;
}
for (int i = 1; i <= n - 2; ++i) ans ^= 1ll * i * p[i];
}
void decode(int *p, int n) { // prufer -> father
for (int i = 1; i <= n; ++i) deg[i] = 0;
for (int i = 1; i <= n - 2; ++i) ++deg[p[i]]; p[n - 1] = n;
for (int i = 1, j = 1; i < n; ++i, ++j) {
while (deg[j]) ++j; f[j] = p[i];
while (i < n && --deg[p[i]] == 0 && p[i] < j) f[p[i]] = p[i + 1], ++i;
}
for (int i = 1; i <= n - 1; ++i) ans ^= 1ll * i * f[i];
}
}
int main() {
read(n); read(type);
for (int i = 1; i <= n - type; ++i) read(a[i]);
if (type == 1) prufer::encode(a, n);
else prufer::decode(a, n);
printf("%lld\n", ans);
return 0;
}
// 强连通分量
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
const int M = 200010;
int head[N], pnt[M], nxt[M], E, n, m;
int dfn[N], low[N], tim, sta[N], top, scc[N], cnt;
void adde(int u, int v) {
E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E;
}
void tarjan(int u) {
dfn[u] = low[u] = ++tim;
sta[++top] = u;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (!scc[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
++cnt;
do {
scc[sta[top]] = cnt;
} while (sta[top--] != u);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
adde(u, v); adde(v, u);
}
for (int i = 1; i <= n; ++i) if (!dfn[i]) top = 0, tarjan(i);
return 0;
}
// 最小斯坦纳树
// https://www.luogu.com.cn/problem/P6192
#include <bits/stdc++.h>
template <typename Tp>
inline void read(Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template <typename Tp, typename... Args>
void read(Tp &t, Args &...args) { read(t); read(args...); }
using namespace std;
typedef long long ll;
const int N = 105;
const int M = 1010;
const int inf = 0x3f3f3f3f;
int head[N], pnt[M], nxt[M], wth[M], E;
int n, m, k, id[N], _id, ful;
int dp[1 << 10][N];
void adde(int u, int v, int w) {
E++; pnt[E] = v; wth[E] = w; nxt[E] = head[u]; head[u] = E;
}
struct dat {
int u, d;
bool operator<(const dat a) const {
return d > a.d;
}
};
bool vis[N];
priority_queue<dat> Q;
void dijk(int S) {
memset(vis, 0, sizeof(vis));
while (!Q.empty()) {
int u = Q.top().u; Q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!vis[v] && dp[S][v] > dp[S][u] + wth[i]) {
dp[S][v] = dp[S][u] + wth[i];
Q.push(dat{v, dp[S][v]});
}
}
}
}
int main() {
read(n, m, k);
for (int i = 1; i <= m; ++i) {
int u, v, w; read(u, v, w);
adde(u, v, w); adde(v, u, w);
}
memset(id, -1, sizeof(id));
for (int i = 1; i <= k; ++i) {
int x; read(x); id[x] = _id++;
}
ful = (1 << k) - 1;
memset(dp, 0x3f, sizeof(dp));
for (int i = 1; i <= n; ++i) if (id[i] != -1)
dp[1 << id[i]][i] = 0;
for (int S = 1; S <= ful; ++S) {
for (int i = 1; i <= n; ++i) {
for (int sub = (S - 1) & S; sub; sub = (sub - 1) & S)
dp[S][i] = min(dp[S][i], dp[sub][i] + dp[S ^ sub][i]);
if (dp[S][i] < inf) {
Q.push(dat{i, dp[S][i]});
}
}
dijk(S);
}
int ans = inf;
for (int i = 1; i <= n; ++i)
ans = min(ans, dp[ful][i]);
printf("%d\n", ans);
return 0;
}
// 割点(割顶)
#include <bits/stdc++.h>
using namespace std;
const int N = 20010;
const int M = 200010;
int head[N], pnt[M], nxt[M], E, n, m;
int dfn[N], low[N], tim, root;
bool vcut[N];
void adde(int u, int v) {
E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E;
}
void tarjan(int u) {
dfn[u] = low[u] = ++tim;
int child = 0;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!dfn[v]) {
tarjan(v); low[u] = min(low[u], low[v]);
if (dfn[u] <= low[v]) {
++child;
if (u != root || child >= 2) vcut[u] = true;
}
} else low[u] = min(low[u], dfn[v]);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
adde(u, v); adde(v, u);
}
for (int i = 1; i <= n; ++i) if (!dfn[i]) root = i, tarjan(i);
return 0;
}
// 点双连通分量 & 缩点
#include <bits/stdc++.h>
using namespace std;
const int N = 20010;
const int M = 200010;
int head[N], pnt[M], nxt[M], E, n, m;
int headc[N], pntc[M], nxtc[M], Ec;
int dfn[N], low[N], tim, root, sta[N], top;
bool vcut[N];
vector<int> dcc[N]; int col[N], cnt;
int tot, new_id[N];
void adde(int u, int v) {
E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E;
}
void addec(int u, int v) {
Ec++; pntc[Ec] = v; nxtc[Ec] = headc[u]; headc[u] = Ec;
}
void tarjan(int u) {
dfn[u] = low[u] = ++tim;
sta[++top] = u;
if (u == root && head[u] == 0) { // 孤立点
dcc[++cnt].push_back(u); return;
}
int child = 0;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (!dfn[v]) {
tarjan(v); low[u] = min(low[u], low[v]);
if (dfn[u] <= low[v]) {
++child;
if (u != root || child >= 2) vcut[u] = true;
++cnt;
while (1) {
dcc[cnt].push_back(sta[top]);
if (sta[top--] == v) break;
}
dcc[cnt].push_back(u);
}
} else low[u] = min(low[u], dfn[v]);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
adde(u, v); adde(v, u);
}
for (int i = 1; i <= n; ++i) if (!dfn[i]) root = i, top = 0, tarjan(i);
// 割点可以属于多个 v-DCC,其它点只属于一个 v-DCC
// 缩点: 割点重新编号,每个 v-DCC 向它包含的割点连边
tot = cnt;
for (int i = 1; i <= n; ++i) if (vcut[i]) new_id[i] = ++tot;
for (int i = 1; i <= cnt; ++i) {
for (auto &u : dcc[i]) {
if (vcut[u]) {
addec(i, new_id[u]);
addec(new_id[u], i);
} else col[u] = i;
}
}
return 0;
}
// 点分树 luogu-P6329
#include <bits/stdc++.h>
#define see(x) cerr<<#x<<"="<<x<<endl;
#define _max(x,y) ((x>y)?x:y)
#define _min(x,y) ((x<y)?x:y)
using namespace std;
typedef long long ll;
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
const int N = 100010;
const int M = 20;
int head[N], pnt[N << 1], nxt[N << 1], E;
int val[N], son[N], siz[N], dep[N], mxdep, size, root, n, m;
int far[N], Dep[N], dist[M][N];
struct trearr {
vector<int> t; int n;
void init(int sz) {t.resize(sz + 1, 0); n = sz;}
void add(int x, int v) {for (; x <= n; x += x & -x) t[x] += v;}
int sum(int x) {int r = 0; for (x = _min(x, n); x > 0; x -= x & -x) r += t[x]; return r;}
} Dt[N], dt[N];
trearr *ps[N];
bool vis[N];
void adde(int u, int v) { E++; pnt[E] = v; nxt[E] = head[u]; head[u] = E; }
void getroot(int u, int f) {
siz[u] = 1; son[u] = 0;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == f || vis[v]) continue;
getroot(v, u);
siz[u] += siz[v];
son[u] = _max(son[u], siz[v]);
}
son[u] = _max(son[u], size - siz[u]);
if (son[u] < son[root]) root = u;
}
void dfs(int u, int f, int S, int fr) {
Dt[S].add(dep[u], val[u]); dt[fr].add(dep[u], val[u]);
dist[Dep[S]][u] = dep[u];
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == f || vis[v]) continue;
dfs(v, u, S, fr);
}
}
void DFS(int u, int f, int d) {
dep[u] = d; siz[u] = 1; mxdep = _max(mxdep, d);
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == f || vis[v]) continue;
DFS(v, u, d + 1); siz[u] += siz[v];
}
}
void vdiv(int u) {
int mx = 0;
vector<pair<int, int> > sons;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (vis[v]) continue;
mxdep = 0; DFS(v, u, 1); mx = _max(mx, mxdep);
size = siz[v]; root = 0; getroot(v, u);
sons.push_back(make_pair(v, root)); far[root] = u;
dt[root].init(mxdep);
}
Dt[u].init(mx);
for (int i = 0; i < sons.size(); ++i)
dfs(sons[i].first, u, u, sons[i].second);
vis[u] = 1;
for (int i = 0; i < sons.size(); ++i) {
Dep[sons[i].second] = Dep[u] + 1;
vdiv(sons[i].second);
}
}
int ask(int x, int K) {
int ret = 0, fr = -1;
for (int u = x; u; u = far[u]) {
int d = K - dist[Dep[u]][x];
if (d > 0) {
ret += Dt[u].sum(d);
if (fr != -1)
ret -= dt[fr].sum(d);
}
if (d >= 0) ret += val[u];
fr = u;
}
return ret;
}
void modify(int x, int vl) {
int fr = x;
for (int u = far[x]; u; u = far[u]) {
int d = dist[Dep[u]][x];
Dt[u].add(d, -val[x]); dt[fr].add(d, -val[x]);
Dt[u].add(d, vl); dt[fr].add(d, vl);
fr = u;
}
val[x] = vl;
}
int main() {
red(n); red(m);
for (int i = 1; i <= n; ++i) red(val[i]);
for (int i = 1; i < n; ++i) {
int u, v; red(u); red(v);
adde(u, v); adde(v, u);
}
size = n; son[root = 0] = n;
getroot(1, 0);
vdiv(root);
int lst = 0;
while (m--) {
int op, x, y; red(op); red(x); red(y);
x ^= lst; y ^= lst;
if (op == 0) {
lst = ask(x, y);
printf("%d\n", lst);
} else
modify(x, y);
}
return 0;
}
/*
luogu - P2495 [SDOI2011]消耗战
虚树板子,建树看 build()
Oi-wiki(虚树) --> https://oi-wiki.org/graph/virtual-tree/
*/
#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
const int N = 300000;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int head[N], pnt[N << 1], nxt[N << 1], wth[N << 1], E;
int dfn[N], tim, h[N], K;
int n, Q, fa[N], deg[N], W[N], ty[N];
ll Dp[N];
namespace LCA {
int siz[N], son[N], top[N], fa[N], dep[N];
void dfs1(int u, int f, int d) {
fa[u] = f; dep[u] = d; siz[u] = 1;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == f) continue;
dfs1(v, u, d + 1); siz[u] += siz[v];
if (siz[son[u]] < siz[v]) son[u] = v;
}
}
void dfs2(int u, int topf) {
top[u] = topf;
if (son[u]) dfs2(son[u], topf);
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
int lca(int u, int v) {
int fu = top[u], fv = top[v];
while (fu != fv) {
if (dep[fu] < dep[fv]) swap(fu, fv), swap(u, v);
u = fa[fu]; fu = top[u];
}
return (dep[u] < dep[v]) ? u : v;
}
}
using LCA::lca;
void adde(int u, int v, int w) {
E++; pnt[E] = v; nxt[E] = head[u]; wth[E] = w; head[u] = E;
}
bool cmp(int x, int y) { return dfn[x] < dfn[y];}
void dfs(int u, int f) {
dfn[u] = ++tim;
for (int i = head[u]; i; i = nxt[i]) {
int v = pnt[i];
if (v == f) continue;
W[v] = min(W[u], wth[i]);
dfs(v, u);
}
}
// begin : build virtual tree
int st[N], top, b[N], tot; // b[1:tot] are the nodes in virtual tree
void build() {
sort(h + 1, h + K + 1, cmp);
st[top = 1] = 1; deg[1] = fa[1] = 0; b[tot = 1] = 1;
for (int i = 1; i <= K; ++i) {
if (h[i] == 1) continue;
int lc = lca(h[i], st[top]);
if (lc != st[top]) {
while (dfn[lc] < dfn[st[top - 1]]) {
fa[st[top]] = st[top - 1];
++deg[st[top - 1]];
top--;
}
if (dfn[lc] > dfn[st[top - 1]]) {
fa[st[top]] = lc; deg[lc] = 1;
fa[lc] = 0, st[top] = lc; b[++tot] = lc;
} else {
fa[st[top--]] = lc; ++deg[lc];
}
}
st[++top] = h[i]; b[++tot] = h[i];
deg[h[i]] = fa[h[i]] = 0;
}
for (int i = 2; i <= top; ++i) fa[st[i]] = st[i - 1], ++deg[st[i - 1]];
}
// end build
ll solve() {
queue<int> q;
for (int i = 1; i <= tot; ++i) {
Dp[b[i]] = 0;
if (deg[b[i]] == 0) q.push(b[i]);
}
while (!q.empty()) {
int u = q.front(); q.pop();
if (u == 1) break;
if (ty[u]) Dp[fa[u]] += W[u];
else Dp[fa[u]] += min((ll)W[u], Dp[u]);
--deg[fa[u]];
if (deg[fa[u]] == 0) q.push(fa[u]);
}
return Dp[1];
}
int main() {
red(n);
for (int i = 1; i < n; ++i) {
int u, v, w; red(u); red(v); red(w);
adde(u, v, w); adde(v, u, w);
}
W[1] = inf;
dfs(1, 0);
LCA::dfs1(1, 0, 0); LCA::dfs2(1, 1);
red(Q);
while (Q--) {
red(K);
for (int i = 1; i <= K; ++i) red(h[i]), ty[h[i]] = 1;
build();
ll ans = solve();
printf("%lld\n", ans);
for (int i = 1; i <= K; ++i) ty[h[i]] = 0;
}
}
// P3812 【模板】线性基
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int B = 52;
ll d[B], x;
int tot, n;
void insert(ll x) {
for (int i = B - 1; i >= 0; --i) if ((x >> i) & 1) {
if (d[i] == 0) {
d[i] = x, ++tot; return ;
}
x ^= d[i];
}
}
ll getmax() {
ll ret = 0;
for (int i = B - 1; i >= 0; --i) if ((ret ^ d[i]) > ret) ret ^= d[i];
return ret;
}
ll getmin() {
if (tot < n) return 0;
for (int i = 0; i < B; ++i) if (d[i] != 0) return d[i];
return -1;
}
void work() {
for (int i = 1; i < B; ++i)
for (int j = 0; j < i; ++j)
if ((d[i] >> j) & 1) d[i] ^= d[j];
}
ll getkth(ll k) {
if (k == 1 && tot < n) return 0;
if (tot < n) --k;
work(); ll ret = 0;
for (int i = 0; i < B; ++i, k >>= 1) if (d[i] && (k & 1)) ret ^= d[i];
return ret;
}
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> x;
insert(x);
}
printf("%lld\n", getmax());
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 20;
ll a[N], b[N]; int n;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {x = 1, y = 0; return a;}
ll d = exgcd(b, a % b, x, y);
swap(x, y); y -= a / b * x;
return d;
}
ll inv(ll a, ll b) {
ll x, y; exgcd(a, b, x, y);
return (x % b + b) % b;
}
// x=ai (mod mi) gcd(m1,m2....mn)=1
ll CRT(int n, ll a[], ll m[]) {
ll M = 1, x = 0;
for (int i = 1; i <= n; i++) M *= m[i];
for (int i = 1; i <= n; i++)
x = (x + (M / m[i]) * inv(M / m[i], m[i]) % M * a[i] % M) % M;
return x;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%lld%lld", &a[i], &b[i]);
ll ans = CRT(n, b, a);
printf("%lld\n", ans);
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return !b ? a : gcd(b, a % b);}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {x = 1, y = 0; return a;}
ll d = exgcd(b, a % b, x, y);
swap(x, y); y -= a / b * x;
return d;
}
ll inv(ll a, ll b) {
ll x, y; exgcd(a, b, x, y);
return (x % b + b) % b;
}
ll BSGS(ll a, ll n, ll p) {
ll ans = p, t = ceil(sqrt(p)), dt = 1;
map<ll, ll> hash;
for (ll B = 1; B <= t; B++) dt = (dt * a) % p, hash[(dt * n) % p] = B;
for (ll A = 1, num = dt; A <= t;
A++, num = (num * dt) % p) if (hash.find(num) != hash.end()) ans = min(ans, A * t - hash[num]);
return ans;
}
//a^x=n (mod p)
ll EXBSGS(ll a, ll n, ll p) {
int k = 0; ll d, ad = 1;
while ((d = gcd(a, p)) != 1) {
if (n % d) return -1;
n /= d, p /= d; ad *= a / d; ad %= p; k++;
}
n = (n * inv(ad, p)) % p;
ll res = BSGS(a, n, p);
if (res == p) return -1;
return res + k;
}
ll a, p, n;
int main() {
while (cin >> a >> p >> n) {
if (a == 0 && p == 0 && n == 0) break;
ll ans = EXBSGS(a, n, p);
if (ans == -1) printf("No Solution\n");
else printf("%lld\n", ans);
}
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
ll a[N], b[N]; int n;
ll mul(ll a, ll b, ll mod) {
ll r = 0;
a = (a % mod + mod) % mod;
b = (b % mod + mod) % mod;
while (b) {
if (b & 1) r = (r + a) % mod;
a = (a << 1) % mod; b >>= 1;
} return r;
}
ll gcd(ll a, ll b) {
return !b ? a : gcd(b, a % b);
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {x = 1, y = 0; return a;}
ll d = exgcd(b, a % b, x, y);
swap(x, y); y -= a / b * x;
return d;
}
// x=ai (mod mi)
ll EXCRT(int n, ll a[], ll m[]) {
for (int i = 2; i <= n; i++) {
ll d = gcd(m[i - 1], m[i]), x, y;
if ((a[i] - a[i - 1]) % d != 0) return -1; // 无解
exgcd(m[i - 1] / d, m[i] / d, x, y);
m[i] = m[i] / gcd(m[i], m[i - 1]) * m[i - 1];
a[i] = (a[i - 1] + mul(mul((a[i] - a[i - 1]) / d, x, m[i]), m[i - 1], m[i])) % m[i];
a[i] = (a[i] + m[i]) % m[i];
}
return a[n];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld%lld", &a[i], &b[i]);
ll ans = EXCRT(n, b, a);
printf("%lld\n", ans);
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mul(ll a, ll b, ll p) {
ll l = ((b >> 30) % p * (1ll << 30) % p) % p;
ll r = (b & ((1ll << 30) - 1ll)) % p;
return ((l * a) % p + (r * a) % p) % p;
}
ll fpow(ll a, ll b, ll p) {
ll r = 1ll;
while (b) {
if (b & 1) r = mul(r, a, p);
a = mul(a, a, p);
b >>= 1;
}
return r;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {x = 1ll, y = 0; return a;}
ll d = exgcd(b, a % b, x, y); swap(x, y);
y -= (a / b) * x; return d;
}
ll inv(ll a, ll p) {
ll iv, k;
exgcd(a, p, iv, k);
return (iv % p + p) % p;
}
// calc (n!/p^c) mod p^k which gcd(n!/p^c,p^k)=1
ll fact(ll n, ll p, ll pk) {
if (!n) return 1ll;
ll ret = 1ll;
for (ll i = 1ll; i <= pk; i++) {
if (i % p) ret = ret * i % pk;
}
ret = fpow(ret, n / pk, pk);
for (ll i = 1ll; i <= n % pk; i++) {
if (i % p) ret = ret * i % pk;
}
return ret * fact(n / p, p, pk) % pk;
}
ll C(ll n, ll m, ll p, ll pk) {
if (n < m) return 0;
ll f1 = fact(n, p, pk), f2 = inv(fact(m, p, pk), pk), f3 = inv(fact(n - m, p, pk), pk);
ll cnt = 0;
for (ll i = n; i; i /= p) cnt += i / p;
for (ll i = m; i; i /= p) cnt -= i / p;
for (ll i = n - m; i; i /= p) cnt -= i / p;
return f1 * f2 % pk * f3 % pk * fpow(p, cnt, pk) % pk;
}
ll CRT(int n, ll a[], ll m[]) {
ll M = 1, ret = 0;
for (int i = 1; i <= n; i++) M *= m[i];
for (int i = 1; i <= n; i++)
ret = (ret + a[i] * (M / m[i]) % M * inv(M / m[i], m[i])) % M;
return (ret % M + M) % M;
}
ll exlucas(ll n, ll m, ll p) {
ll pk[24], c[24]; int tot = 0;
for (ll i = 2ll; i <= p / i; i++) {
if (p % i == 0) {
pk[++tot] = 1ll;
while (p % i == 0) p /= i, pk[tot] *= i;
c[tot] = C(n, m, i, pk[tot]);
}
}
if (p > 1) pk[++tot] = p, c[tot] = C(n, m, p, p);
return CRT(tot, c, pk);
}
int main() {
ll n, m, p;
cin >> n >> m >> p;
cout << exlucas(n, m, p) << endl;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
double a[N][N];
int n;
void init() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n + 1; j++)
scanf("%lf", &a[i][j]);
}
void solve() {
for (int j = 1; j <= n; j++) {
int mxp = j;
for (int i = j + 1; i <= n; i++)
if (fabs(a[i][j]) > fabs(a[mxp][j])) mxp = i;
for (int i = 1; i <= n + 1; i++)
swap(a[j][i], a[mxp][i]);
if (a[j][j] == 0) {
printf("No Solution\n");
return ;
}
for (int i = 1; i <= n; i++) {
if (i == j) continue;
double tmp = a[i][j] / a[j][j];
for (int k = 1; k <= n + 1; k++)
a[i][k] -= a[j][k] * tmp;
}
}
for (int i = 1; i <= n; i++)
printf("%.2lf\n", a[i][n + 1] / a[i][i]);
}
int main() {
init();
solve();
return 0;
}
// 原根
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int p[N], tot, phi[N]; // p[] 素数,phi[] 欧拉函数
bool v[N], has[N]; // v[] 是否是素数, is[] 是否有原根
int Ts;
typedef long long ll;
ll fpow(ll a, ll b, ll p) {ll r = 1; for (; b; b >>= 1, a = (a * a) % p) if (b & 1) r = (r * a) % p; return r;}
int gcd(int a, int b) {return !b ? a : gcd(b, a % b);}
void init(int n) { // 预处理欧拉函数,素数,及那些数有原根
phi[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!v[i]) p[++tot] = i, phi[i] = i - 1;
for (int j = 1; j <= tot && p[j]*i <= n; ++j) {
v[p[j]*i] = 1;
if (i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * (p[j] - 1);
}
}
has[2] = has[4] = 1;
for (int i = 2; i <= tot; ++i) for (ll j = p[i]; j <= n; j *= p[i]) has[j] = 1, (j * 2 <= n)
&& (has[j * 2] = 1);
}
void devide(int x, vector<int> &ret) { // 分解质因数
ret.clear();
for (int i = 1; 1ll * p[i]*p[i] <= x; ++i) if (x % p[i] == 0) {
ret.push_back(p[i]);
while (x % p[i] == 0) x /= p[i];
}
if (x > 1) ret.push_back(x);
}
bool hasroot(int n) { // 判断一个数是否有原根
if (n == 2 || n == 4) return 1;
if (n % 2 == 0) n /= 2;
if (n % 2 == 0) return 0;
for (int i = 2; 1ll * p[i]*p[i] <= n; ++i) if (n % p[i] == 0) {
while (n % p[i] == 0) n /= p[i];
return (n == 1);
}
return 1;
}
void Getroot(int m, vector<int> &res) {
res.clear();
if (!has[m]) return ;
vector<int> factor;
devide(phi[m], factor);
int g = 1, mphi = phi[m];
while (true) {
bool fg = 1;
if (gcd(g, m) != 1) fg = 0; //i不存在模n的阶
else for (int i = 0; i < (int)factor.size(); ++i) {
if (fpow(g, mphi / factor[i], m) == 1ll) {fg = 0; break;}
}
if (fg) break;
++g;
}
ll pw = 1;
for (int s = 1; (int)res.size() < phi[mphi]; ++s) {
pw = (pw * g) % m;
if (gcd(s, mphi) == 1) res.push_back(pw);
}
sort(res.begin(), res.end());
}
int main() {
init(1e6);
scanf("%d", &Ts);
while (Ts--) {
int n, d; // 找 n 的所有原根
scanf("%d%d", &n, &d);
vector<int> ans;
Getroot(n, ans);
printf("%d\n", (int)ans.size());
for (int i = d - 1; i < (int)ans.size(); i += d) printf("%d ", ans[i]);
printf("\n");
}
}
// 数值积分,自适应辛普森法
#include <cmath>
#include <cstdio>
using namespace std;
typedef double db;
// 要计算的函数
db f(db x) {
return x * x * x;
}
// 辛普森公式 = (r - l) / 6 * (f(l) + f(r) + 4f((l + r) / 2))
db simpon(db l, db r) {
db mid = (l + r) / 2.0;
return (r - l) * (f(l) + f(r) + f(mid) * 4.0) / 6.0;
}
db simpon(db l, db r, db eps, db ans, int step) {
db mid = (l + r) / 2.0;
db fl = simpon(l, mid), fr = simpon(mid, r);
if (fabs(fl + fr - ans) <= 15.0 * eps && step < 0) return fl + fr + (fl + fr - ans) / 15.0;
return simpon(l, mid, eps / 2.0, fl, step - 1) + simpon(mid, r, eps / 2.0, fr, step - 1);
}
db calc(db l, db r, db eps) {
return simpon(l, r, eps, simpon(l, r), 12);
}
// 第一类斯特林数·行
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cstring>
#define clr(f,n) memset(f,0,sizeof(long long)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(long long)*(n))
#define _max(x,y) ((x>y)?x:y)
#define _min(x,y) ((x<y)?x:y)
#define MOD(x) ((x)<mod?(x):((x)%mod))
using namespace std;
typedef long long ll;
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp> bool umax(_Tp &x, _Tp y) {return (x < y) ? (x = y, true) : (false);}
template<typename _Tp> bool umin(_Tp &x, _Tp y) {return (x > y) ? (x = y, true) : (false);}
const int N = (1 << 19);
const int mod = 167772161;
const int _G = 3;
const int _iG = 55924054;
int rev[N], rev_n;
ll inv[N], ifac[N], fac[N];
ll fpow(ll a, ll b = mod - 2) {
ll r = 1;
for (; b; b >>= 1, a = MOD(a * a)) if (b & 1) r = MOD(r * a);
return r;
}
void prerev(int n) {
if (rev_n == n) return ;
for (int i = 0; i < n; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
rev_n = n;
}
void NTT(ll f[], int n, int fg) {
prerev(n);
for (int i = 0; i < n; ++i) if (i < rev[i]) swap(f[i], f[rev[i]]);
for (int h = 2; h <= n; h <<= 1) {
int len = h >> 1;
ll Dt = fpow((fg == 1) ? _G : _iG, (mod - 1) / h), w;
for (int j = 0; j < n; j += h) { // j<n !! not j<=n
w = 1;
for (int k = j; k < j + len; ++k) {
ll tt = MOD(w * f[k + len]);
f[k + len] = f[k] - tt; (f[k + len] < 0) &&(f[k + len] += mod);
f[k] = f[k] + tt; (f[k] >= mod) &&(f[k] -= mod);
w = MOD(w * Dt);
}
}
}
if (fg == -1) {
ll invn = fpow(n, mod - 2);
for (int i = 0; i < n; ++i) f[i] = MOD(f[i] * invn);
}
}
ll S1[N];
int n;
// change f(x) to f(x+n)
void change(ll f[], int n) {
static ll g[N];
int nn;
for (nn = 1; nn < (2 * n + 2); nn <<= 1) ;
clr(g, nn); clr(f + n + 1, nn - n - 1);
for (int i = 0; i <= n; ++i) f[i] = MOD(f[i] * fac[i]);
for (int i = 0, pw = 1; i <= n; ++i, pw = MOD((ll)pw * n)) g[n - i] = MOD((ll)pw * ifac[i]);
NTT(f, nn, 1); NTT(g, nn, 1);
for (int i = 0; i < nn; ++i) f[i] = MOD(f[i] * g[i]);
NTT(f, nn, -1);
for (int i = 0; i <= n; ++i)
f[i] = MOD(f[i + n] * ifac[i]);
clr(f + n + 1, nn - n - 1);
}
void GetS1(ll f[], int n) {
static int stk[50], top;
static ll g[N];
top = 0;
while (n) stk[++top] = n, n >>= 1;
clr(f, n << 1); f[1] = 1;
for (int tt = top - 1; tt >= 1; --tt) {
int now = stk[tt], len = stk[tt + 1], nn;
cpy(g, f, len + 1);
change(g, len);
for (nn = 1; nn < (len * 2 + 2); nn <<= 1) ;
NTT(f, nn, 1); NTT(g, nn, 1);
for (int i = 0; i < nn; ++i) f[i] = MOD(f[i] * g[i]);
NTT(f, nn, -1);
if ((len << 1) + 1 == now) {
// * (x+now-1)
for (int i = now; i >= 0; --i) {
f[i + 1] = MOD(f[i + 1] + f[i]);
f[i] = MOD(f[i] * (now - 1));
}
}
}
}
int main() {
red(n);
fac[0] = fac[1] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
for (int i = 2; i <= n + 1; ++i) fac[i] = MOD(fac[i - 1] * i);
for (int i = 2; i <= n + 1; ++i) inv[i] = MOD((mod - mod / i) * inv[mod % i]);
for (int i = 2; i <= n + 1; ++i) ifac[i] = MOD(ifac[i - 1] * inv[i]);
GetS1(S1, n);
for (int i = 0; i <= n; ++i)
printf("%lld ", S1[i]);
printf("\n");
return 0;
}
/*
生活不止眼前的 OI
还有 逻辑 与 并行
*/
// 第二类斯特林数·行
#include <algorithm>
#include <cstdio>
#include <iostream>
#define _max(x,y) ((x>y)?x:y)
#define _min(x,y) ((x<y)?x:y)
#define MOD(x) ((x)<mod?(x):((x)%mod))
using namespace std;
typedef long long ll;
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp> bool umax(_Tp &x, _Tp y) {return (x < y) ? (x = y, true) : (false);}
template<typename _Tp> bool umin(_Tp &x, _Tp y) {return (x > y) ? (x = y, true) : (false);}
const int N = (1 << 19);
const int mod = 167772161;
const int _G = 3;
const int _iG = 55924054;
int rev[N], rev_n;
ll inv[N], ifac[N], fac[N];
ll S2[N], f[N], g[N];
ll fpow(ll a, ll b = mod - 2) {
ll r = 1;
for (; b; b >>= 1, a = MOD(a * a)) if (b & 1) r = MOD(r * a);
return r;
}
void prerev(int n) {
if (rev_n == n) return ;
for (int i = 0; i < n; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
rev_n = n;
}
void NTT(ll f[], int n, int fg) {
prerev(n);
for (int i = 0; i < n; ++i) if (i < rev[i]) swap(f[i], f[rev[i]]);
for (int h = 2; h <= n; h <<= 1) {
int len = h >> 1;
ll Dt = fpow((fg == 1) ? _G : _iG, (mod - 1) / h), w;
for (int j = 0; j < n; j += h) { // j<n !! not j<=n
w = 1;
for (int k = j; k < j + len; ++k) {
ll tt = MOD(w * f[k + len]);
f[k + len] = f[k] - tt; (f[k + len] < 0) &&(f[k + len] += mod);
f[k] = f[k] + tt; (f[k] >= mod) &&(f[k] -= mod);
w = MOD(w * Dt);
}
}
}
if (fg == -1) {
ll invn = fpow(n, mod - 2);
for (int i = 0; i < n; ++i) f[i] = MOD(f[i] * invn);
}
}
int n, k, nn;
int main() {
red(n);
fac[0] = fac[1] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
for (int i = 2; i <= n; ++i) fac[i] = MOD(fac[i - 1] * i);
for (int i = 2; i <= n; ++i) inv[i] = MOD((mod - mod / i) * inv[mod % i]);
for (int i = 2; i <= n; ++i) ifac[i] = MOD(ifac[i - 1] * inv[i]);
for (int k = 0; k <= n; ++k) {
f[k] = ifac[k];
if (k & 1) f[k] = MOD(mod - f[k]);
g[k] = MOD(ifac[k] * fpow(k, n));
}
for (nn = 1; nn < (n * 2 + 2); nn <<= 1) ;
NTT(f, nn, 1); NTT(g, nn, 1);
for (int i = 0; i < nn; ++i) S2[i] = MOD(f[i] * g[i]);
NTT(S2, nn, -1);
for (int i = 0; i <= n; ++i) printf("%lld ", S2[i]);
printf("\n");
return 0;
}
#include <windows.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <ctime>
using namespace std;
string tmp;
int st;
void setclock() {st = clock();}
int getclock() {return clock() - st;}
int ifcpl = 1, test_times = 1e9;
string comd = "-std=c++11 -Wall -O2";
void PrintHelp() {
printf("Uesge:\n");
printf("\tchk <std.cpp> <test.cpp> <mker.cpp> [-t (test-times)] [-q | -c <commond>]\n");
printf("-t (test-times) : run test for (test-times) times\n");
printf("-q : without compile\n");
printf("-c <commond> : commonds for compile\n");
exit(1);
}
void Genarg(int argc, char const *argv[]) {
if (argc < 4) PrintHelp();
for (int i = 4; i < argc; ++i) {
if (strcmp(argv[i], "-q") == 0) ifcpl = 0;
else if (strcmp(argv[i], "-t") == 0) {
++i;
if (i >= argc) PrintHelp();
test_times = atoi(argv[i]);
} else if (strcmp(argv[i], "-c") == 0) {
++i;
if (i >= argc) PrintHelp();
comd = argv[i];
} else PrintHelp();
}
}
int main(int argc, char const *argv[]) {
Genarg(argc, argv);
printf("total: %d test\n", test_times);
if (ifcpl) {
int fg = 0;
printf("building...\n");
tmp = "g++ " + string(argv[1]) + " -o .std " + comd; fg |= system(tmp.c_str());
tmp = "g++ " + string(argv[2]) + " -o .tst " + comd; fg |= system(tmp.c_str());
tmp = "g++ " + string(argv[3]) + " -o .mk " + comd; fg |= system(tmp.c_str());
if (fg) {
printf("complie error!\n");
return 2;
} else
printf("completed!\n");
}
for (int t = 1; t <= test_times; ++t) {
printf("test #%d\n", t);
system(".mk > .in.txt");
int Tstd, Ttst;
setclock(); system(".std < .in.txt > .ans.txt"); Tstd = getclock(); printf("std: %dms ", Tstd);
setclock(); system(".tst < .in.txt > .out.txt"); Ttst = getclock(); printf("tst: %dms\n", Ttst);
if (system("fc .ans.txt .out.txt")) {
printf("Wrong Answer !\n");
getchar();
}
}
return 0;
}
#include <bits/stdc++.h>
#ifndef DEBUGER
#define DEBUGER
#ifdef DEBUG
#define see(a) cerr<<#a<<" = "<<a<<" "
#define seeln(a) cerr<<#a<<" = "<<a<<endl
#define put(a) cerr<<a
#define outarr(_a,_l,_r) for(int _i=(_l);_i<=(_r);_i++) cerr<<#_a"["<<_i<<"]="<<_a[_i]<<" ";cerr<<endl;
#define Outarr(_a,_l,_r) cerr<<#_a<<" ["<<_l<<", "<<_r<<"] : "; for(int i=(_l);i<=(_r);++i) cerr<<_a[i]<<" ";cerr<<endl;
#define out(a) cerr<<a<<" "
#define outln(a) cerr<<a<<endl
#else
#define see(a) ;
#define seeln(a) ;
#define put(a);
#define outarr(_a,_l,_r) ;
#define Outarr(_a,_l,_r) ;
#define out(a) ;
#define outln(a) ;
#endif
using namespace std;
template<typename Tp>
ostream &operator<<(ostream &out, vector<Tp> vt) {
out << "vector of size = " << vt.size() << " : { " ;
for (size_t i = 0; i < vt.size(); ++i) out << vt[i] << ", ";
return out << "} ";
}
template<typename Tp>
istream &operator>>(istream &in, vector<Tp> &vt) {
for (size_t i = 0; i < vt.size(); ++i) in >> vt[i];
return in;
}
template<typename Tp>
ostream &operator<<(ostream &out, set<Tp> st) {
out << "set of size = " << st.size() << " : { " ;
for (auto it = st.begin(); it != st.end(); ++it) out << *it << ", ";
return out << "} ";
}
template<typename Tp>
ostream &operator<<(ostream &out, multiset<Tp> st) {
out << "multiset of size = " << st.size() << " : { " ;
for (auto it = st.begin(); it != st.end(); ++it) out << *it << ", ";
return out << "} ";
}
template<typename Tp1, typename Tp2>
ostream &operator<<(ostream &out, map<Tp1, Tp2> mp) {
out << "map of size = " << mp.size() << " : { " ;
for (auto it = mp.begin(); it != mp.end(); ++it)
out << "\"" << it->first << "\": " << it->second << ", ";
return out << "} ";
}
template<typename Tp1, typename Tp2>
ostream &operator<<(ostream &out, pair<Tp1, Tp2> P) {
return out << "(" << P.first << ", " << P.second << ")";
}
#endif
#include <iostream>
#include <cstdio>
#ifndef FASTIO
#define FASTIO
class myin {
private:
static const int MAX = 1 << 20;
char buf[MAX], *p1 = buf, *p2 = buf;
inline char gc() {
#ifdef DEBUG
return getchar();
#endif
if (p1 != p2) return *p1++;
p1 = buf; p2 = p1 + fread(buf, 1, MAX, stdin); return (p1 == p2) ? (EOF) : (*p1++);
}
public:
myin &operator>>(char *s) {
char ch = gc();
while (ch == '\n' || ch == '\r' || ch == ' ') ch = gc();
while (ch != '\n' && ch != '\r' && ch != ' ') *s++ = ch, ch = gc();
*s = '\0';
return *this;
}
template <typename Tp>
myin &operator>>(Tp &x) {
x = 0; char ch = gc(); bool f = 0;
while (ch < '0' || ch > '9') {(ch == '-') &&(f ^= 1); ch = gc();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (Tp)(ch ^ 48), ch = gc();
if (f)(x = -x);
return *this;
}
myin &operator>>(double &x) {
x = 0; bool f = 0; char ch = gc();
while (ch < '0' || ch > '9') {(ch == '-') &&(f ^= 1); ch = gc();}
while (ch >= '0' && ch <= '9') x = x * 10 + (double)(ch ^ 48), ch = gc();
if (ch == '.') {
ch = gc(); double e = 0.1;
while (ch >= '0' && ch <= '9') x = x + e * (double)(ch ^ 48), e *= 0.1, ch = gc();
}
if (f) x = -x;
return *this;
}
} fin;
class myout {
private:
static const int MAX = 1 << 20;
char buf[MAX], *p1 = buf, *p2 = buf + MAX;
char dbform[10] = "%.6lf";
inline void pc(const char c) {
#ifdef DEBUG
putchar(c); return ;
#endif
if (p1 != p2) *p1++ = c;
else {fwrite(buf, p1 - buf, 1, stdout); p1 = buf; *p1++ = c;}
}
template <typename _Tp> void write(_Tp x) {
if (x < 0) x = -x, pc('-');
if (x >= (_Tp)10) write(x / 10);
pc(x % 10 + '0');
}
public:
void flush() {fwrite(buf, p1 - buf, 1, stdout); p1 = buf;}
myout &operator<<(const char *s) { for (const char *p = s; *p; ++p) pc(*p); return *this;}
myout &operator<<(char *s) { for (char *p = s; *p; ++p) pc(*p); return *this;}
myout &operator<<(const char s) {pc(s); return *this;}
template <typename Tp> myout &operator<<(Tp x) {write(x); return *this;}
myout &operator<<(myout & (*__pf)(myout &)) {return __pf(*this);}
void setpoint(int n) {
sprintf(dbform + 1, ".%dlf", n);
}
myout &operator<<(double x) {
static char num[100];
sprintf(num, dbform, x);
return *this << num;
}
} fout;
inline myout &edl(myout &out) {out << "\n"; out.flush(); return out;}
#endif
#include <cstdio>
namespace IO {
const int MAX = 1 << 20;
char buf[MAX], Buf[MAX], * p1 = buf, * p2 = buf, * P1 = Buf, * P2 = Buf + MAX;
inline char gc() {
#ifdef DEBUG
return getchar();
#endif
if (p1 != p2) return *p1++;
p1 = buf; p2 = p1 + fread(buf, 1, MAX, stdin); return (p1 == p2) ? (EOF) : (*p1++);
}
inline void pc(const char c) {
#ifdef DEBUG
return putchar(c), void();
#endif
if (P1 != P2) *P1++ = c;
else { fwrite(Buf, P1 - Buf, 1, stdout); P1 = Buf; *P1++ = c; }
}
void readstr(char *s, bool fg = 0) { // fg=1 for getline
char ch = gc();
while (ch == '\n' || ch == '\r' || (!fg && ch == ' ')) ch = gc();
while (ch != '\n' && ch != '\r' && (fg || ch != ' ')) *s++ = ch, ch = gc();
*s = '\0';
}
void writestr(const char *s, char ch = '\0') { for (const char *p = s; *p; ++p) pc(*p); (ch != '\0') &&(pc(ch), 1); }
template <typename _Tp> void read(_Tp &x) {
x = 0; char ch = gc(); int f = 0;
while (ch < '0' || ch > '9') { (ch == '-') &&(f ^= 1); ch = gc(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = gc();
f &&(x = -x);
}
template<typename Tp, typename... Args>void read(Tp &t, Args &... args) { read(t); read(args...); }
template<typename Tp> void write(Tp x, char ch = '\n') {
static int buf[100], d;
if (x == 0) pc('0');
else {
if (x < 0) pc('-'), x = -x;
for (d = 0; x; x /= 10) buf[++d] = x % 10 + 48;
while (d) pc((char)buf[d--]);
}
if (ch != '\0') pc(ch);
}
template <typename Tp, typename... Args> void write(Tp x, Args ...args) { write(x, ' '); write(args...); }
void flush() { fwrite(Buf, P1 - Buf, 1, stdout); P1 = Buf; }
struct _flusher {
~_flusher() { flush(); }
} flusher;
}
using IO::read; using IO::write; using IO::readstr; using IO::writestr;
int main() {
return 0;
}
// 莫队二次离线
#include <bits/stdc++.h>
template <typename Tp>
inline void read(Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') fg ^= 1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
using namespace std;
typedef long long ll;
const int N = 100010;
struct mds {
int l, r, id, fg;
};
vector<mds> mdl[N], mdr[N];
vector<mds>::iterator mt;
vector<int>::iterator it;
int a[N], n, m, K;
int L[N], R[N], t[N], bl[N], B;
ll Fl[N], Fr[N], ans[N];
bool cmp(int x, int y) {
if (bl[L[x]] == bl[L[y]]) return R[x] < R[y];
return L[x] < L[y];
}
void init() {
// init Fr,Fl
for (int i = 1; i < n; ++i) {
// Fr(i) = f([1,i],i+1)
}
for (int i = n - 1; i >= 1; --i) {
// Fl(i) = f([i+1,n],i)
}
for (int i = 2; i <= n; ++i) Fl[i] += Fl[i - 1], Fr[i] += Fr[i - 1];
}
void solve() {
for (int x = 1; x <= n; ++x) {
// updata(a[x])
for (mt = mdr[x].begin(); mt != mdr[x].end(); ++mt)
for (int i = mt->l; i <= mt->r; ++i) ans[mt->id] += mt->fg * (1/*query(a[i])*/);
}
for (int x = n; x >= 1; --x) {
// updata(a[x])
for (mt = mdl[x].begin(); mt != mdl[x].end(); ++mt)
for (int i = mt->l; i <= mt->r; ++i) ans[mt->id] += mt->fg * (1/*query(a[i])*/);
}
}
int main() {
read(n); read(m); read(K);
for (int i = 1; i <= n; ++i) read(a[i]);
B = sqrt(n);
for (int i = 1; i <= n; ++i) bl[i] = (i - 1) / B + 1;
for (int i = 1; i <= m; ++i) read(L[i]), read(R[i]), t[i] = i;
sort(t + 1, t + m + 1, cmp);
init();
int l = 1, r = 1;
for (int i = 1; i <= m; ++i) {
int id = t[i];
if (r < R[id]) {
ans[id] += Fr[R[id] - 1] - Fr[r - 1];
mdr[l - 1].push_back(mds{ r + 1, R[id], id, -1 }); r = R[id];
}
if (l > L[id]) {
ans[id] += Fl[l - 1] - Fl[L[id] - 1];
mdl[r + 1].push_back(mds{ L[id], l - 1, id, -1 }); l = L[id];
}
if (r > R[id]) {
ans[id] -= Fr[r - 1] - Fr[R[id] - 1];
mdr[l - 1].push_back(mds{ R[id] + 1, r, id, 1 }); r = R[id];
}
if (l < L[id]) {
ans[id] -= Fl[L[id] - 1] - Fl[l - 1];
mdl[r + 1].push_back(mds{ l, L[id] - 1, id, 1 }); l = L[id];
}
}
solve();
for (int i = 1; i <= m; ++i) ans[t[i]] += ans[t[i - 1]];
for (int i = 1; i <= m; ++i)
printf("%lld\n", ans[i]);
return 0;
}
/*
FFT 快速傅立叶变换
加法卷积
*/
#include <bits/stdc++.h>
#define _max(x,y) ((x>y)?x:y)
#define _min(x,y) ((x<y)?x:y)
using namespace std;
typedef long long ll;
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp> bool umax(_Tp &x, _Tp y) {return (x < y) ? (x = y, true) : (false);}
template<typename _Tp> bool umin(_Tp &x, _Tp y) {return (x > y) ? (x = y, true) : (false);}
typedef double db;
const int N = 2097152;
const db Pi = acos(-1);
struct com {
db r, i;
com(): r(0), i(0) {}
com(db _r, db _i): r(_r), i(_i) {}
com(int n): r(cos(Pi * 2 / n)), i(sin(Pi * 2 / n)) {} // w_n^1
com operator+(const com &b)const {return com(r + b.r, i + b.i);}
com operator-(const com &b)const {return com(r - b.r, i - b.i);}
com operator*(const com &b)const {return com(r * b.r - i * b.i, i * b.r + r * b.i);}
} A[N], B[N];
int n, m, tot;
namespace sol1 { // 分治版FFT
com sav[N];
// flag = 1 DFT flag = -1 IDFT
void FFT(com *f, int n, int flag) {
if (n == 1) return ;
com *fl = f, *fr = f + n / 2, Dt(n), w(1, 0);
Dt.i *= flag;
for (int i = 0; i < n; ++i) sav[i] = f[i];
for (int i = 0; i < n / 2; ++i) fl[i] = sav[i << 1], fr[i] = sav[i << 1 | 1];
FFT(fl, n / 2, flag); FFT(fr, n / 2, flag);
for (int i = 0; i < n / 2; ++i) {
com tmp = w * fr[i];
sav[i] = fl[i] + tmp;
sav[i + n / 2] = fl[i] - tmp;
w = w * Dt;
}
for (int i = 0; i < n; ++i) f[i] = sav[i];
}
}
namespace sol2 { // 迭代版FFT (小常数)
int rev[N];
void FFT(com f[], int n, int fg) {
for (int i = 0; i < n; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
for (int i = 0; i < n; ++i)(i < rev[i]) && (swap(f[i], f[rev[i]]), 1);
for (int h = 2; h <= n; h <<= 1) {
com Dt(h), w, tt; Dt.i *= fg;
int len = (h >> 1);
for (int j = 0; j < n; j += h) {
w = com(1, 0);
for (int k = j; k < j + len; ++k) {
tt = f[k + len] * w;
f[k + len] = f[k] - tt;
f[k] = f[k] + tt;
w = w * Dt;
}
}
}
}
}
int main() {
red(n); red(m);
for (int i = 0; i <= n; ++i) scanf("%lf", &A[i].r);
for (int i = 0; i <= m; ++i) scanf("%lf", &B[i].r);
tot = n + m; n = ceil(log2(n + m + 2)); n = 1 << n;
using namespace sol2;
FFT(A, n, 1); FFT(B, n, 1);
for (int i = 0; i < n; ++i) A[i] = A[i] * B[i];
FFT(A, n, -1);
for (int i = 0; i <= tot; ++i) printf("%d ", (int)(A[i].r / n + 0.49));
puts("");
return 0;
}
/*
FMT/FWT 快速莫比乌斯/沃尔什变换
位运算卷积
*/
#include <bits/stdc++.h>
#define re register
#define cpy(f,g,n) memcpy(f,g,sizeof(long long)*(n))
#define clr(f,n) memset(f,0,sizeof(long long)*(n))
#define out(f,n) for(int i=0;i<(n);++i) printf("%lld ",f[i]);puts("")
#define MOD(x) ((x<mod)?(x):((x)%mod))
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
using namespace std;
typedef long long ll;
const int N = 1 << 18;
const int mod = 998244353;
const int inv2 = 499122177;
ll A[N], B[N], C[N], ta[N], tb[N]; int n;
inline void FMT_OR(ll f[], int n, int fg) { // fg=1 for FMT ; fg=0 for IFMT
for (re int h = 2, k = 1; h <= n; h <<= 1, k <<= 1)
for (re int i = 0; i < n; i += h)
for (re int j = 0; j < k; ++j)
f[i + j + k] = MOD(f[i + j + k] + f[i + j] * fg + mod);
}
inline void FMT_AND(ll f[], int n, int fg) { // fg=1 for FMT ; fg=0 for IFMT
for (re int h = 2, k = 1; h <= n; h <<= 1, k <<= 1)
for (re int i = 0; i < n; i += h)
for (re int j = 0; j < k; ++j)
f[i + j] = MOD(f[i + j] + f[i + j + k] * fg + mod);
}
inline void FWT_XOR(ll f[], int n, int fg) { // fg=1 for FWT; fg=1/2(inv 2) for IFWT
ll t;
for (re int h = 2, k = 1; h <= n; h <<= 1, k <<= 1)
for (re int i = 0; i < n; i += h)
for (re int j = 0; j < k; ++j)
t = f[i + j + k], f[i + j + k] = MOD(f[i + j] - t + mod), f[i + j] = MOD(f[i + j] + t),
f[i + j] = MOD(f[i + j] * fg), f[i + j + k] = MOD(f[i + j + k] * fg);
}
void times(ll f[], ll g[], int n) {for (int i = 0; i < n; ++i) f[i] = MOD(f[i] * g[i]);}
int main() {
red(n); n = 1 << n;
for (re int i = 0; i < n; ++i) red(A[i]);
for (re int i = 0; i < n; ++i) red(B[i]);
cpy(ta, A, n); cpy(tb, B, n); FMT_OR(ta, n, 1); FMT_OR(tb, n, 1); times(ta, tb, n); FMT_OR(ta, n, -1);
out(ta, n);
cpy(ta, A, n); cpy(tb, B, n); FMT_AND(ta, n, 1); FMT_AND(tb, n, 1); times(ta, tb, n); FMT_AND(ta, n, -1);
out(ta, n);
cpy(ta, A, n); cpy(tb, B, n); FWT_XOR(ta, n, 1); FWT_XOR(tb, n, 1); times(ta, tb, n); FWT_XOR(ta, n, inv2);
out(ta, n);
}
// 拉格朗日插值法
// L(x)=\sum_{j=0}^n y_j\prod_{i\ne j}\frac{x-x_i}{x_j-x_i}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
const int mod = 1e9 + 7;
int n, k;
ll fpow(ll a, ll b, ll p = mod) {
ll r = 1;
for (; b; b >>= 1, a = (a * a) % p) if (b & 1) r = (r * a) % p;
return r;
}
ll s[N], p[N], fac[N], inv[N], ifac[N];
void init(int n) {
fac[0] = fac[1] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
for (int i = 2; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
for (int i = 2; i <= n; ++i) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
for (int i = 2; i <= n; ++i) ifac[i] = ifac[i - 1] * inv[i] % mod;
}
ll lagrange(int n, ll k, ll x[], ll y[]) { // O(n^2)
ll r = 0;
for (int j = 0; j < n; ++j) {
ll P1 = 1, P2 = 1;
for (int i = 0; i < n; ++i) if (i != j) {
P1 = (P1 * (k - x[i] + mod)) % mod;
P2 = (P2 * (x[j] - x[i] + mod)) % mod;
}
r = (r + y[j] * P1 % mod * fpow(P2, mod - 2, mod) % mod) % mod;
}
return r;
}
ll lagrange_y(int n, ll k, ll y[]) { // 当 x_i = i (i in [0, n]) O(n)
init(n);
p[0] = 1;
for (int i = 0; i < n; ++i) p[i + 1] = p[i] * (k - i + mod) % mod;
s[n] = 1;
for (int i = n; i >= 1; --i) s[i - 1] = s[i] * (k - i + mod) % mod;
ll r = 0;
for (int j = 0; j <= n; ++j) {
ll tmp = p[j] * s[j] % mod * ifac[j] % mod * ifac[n - j] % mod;
r = (r + (ll)(((n - j) & 1) ? (mod - 1) : 1) * y[j] % mod * tmp % mod) % mod;
}
return r;
}
/*
NTT 快速数论变换
FFT的取模形式
*/
#include <bits/stdc++.h>
#define MOD(x) ((x<p)?(x):((x)%p))
template <typename T>
inline void red(T &x) {
x = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (T)(ch ^ 48), ch = getchar();
if (f) x = -x;
}
using namespace std;
typedef long long ll;
const int p = 998244353; // = 119*2^23+1 g=3 是其原根
const int G = 3;
const int invG = 332748118;
const int N = 2097152;
int n, m, rev[N], tot;
ll A[N], B[N];
// NTT 对模数有要求,如果 p = r*2^k+1 是素数,在 mod p 意义下可处理 2^k 以内数据
// 与 FFT 的区别,单位根 w1 = g^((p-1)/n)
ll fpow(ll a, ll b, ll p =::p) {ll r = 1; for (; b; b >>= 1, a = MOD(a * a)) if (b & 1) r = MOD(r * a); return r;}
// fg=1 DFT fg=0 IDFT
void NTT(ll f[], int n, bool fg) {
for (int i = 0; i < n;
++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0); // 可以放到外面预处理
for (int i = 0; i < n; ++i)(rev[i] < i) && (swap(f[i], f[rev[i]]), 1);
for (int h = 2; h <= n; h <<= 1) {
int len = h >> 1;
ll Dt = fpow(fg ? G : invG, (p - 1) / h), w;
for (int j = 0; j < n; j += h) {
w = 1;
for (int k = j; k < j + len; ++k) {
ll tt = MOD(w * f[k + len]);
f[k + len] = f[k] - tt; (f[k + len] < 0) &&(f[k + len] += p);
f[k] = f[k] + tt; (f[k] > p) &&(f[k] -= p);
w = MOD(w * Dt);
}
}
}
if (fg == 0) {
ll invn = fpow(n, p - 2);
for (int i = 0; i < n; ++i) f[i] = MOD(f[i] * invn);
}
}
int main() {
red(n); red(m);
for (int i = 0; i <= n; ++i) red(A[i]);
for (int i = 0; i <= m; ++i) red(B[i]);
tot = n + m + 1;
n = ceil(log2(n + m + 2)); n = 1 << n;
NTT(A, n, 1); NTT(B, n, 1);
for (int i = 0; i < n; ++i) A[i] = MOD(A[i] * B[i]);
NTT(A, n, 0);
for (int i = 0; i < tot; ++i) printf("%lld ", A[i]);
printf("\n");
}
/*
NTT 多项式全家桶
p_mul 乘法; p_inv 求逆; p_div 带余数除法; p_sqrt 开方;
p_ln Ln; p_exp EXP; p_int 积分; p_der 求导; p_pow 快速幂;
DCFFT 分治 FFT 板子;
to be continue ...
多项式三角函数,多项式反三角函数,多项式多点求值,多项式快速差值.....
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define clr(f,n) memset(f,0,sizeof(long long)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(long long)*(n))
#define Outarr(x,n) cerr<<#x<<" : "; for(int i=0;i<n;++i) cerr<<x[i]<<" ";cout<<endl;
#define outarr(x,n) for(int i=0;i<n;++i) printf("%lld%c",x[i],(i==n-1)?'\n':' ');
#define MOD(x) ((x)<mod?(x):((x)%mod))
using namespace std;
template<typename _Tp>
inline void red(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
typedef long long ll;
namespace poly {
const int mod = 998244353;
const int N = (1 << 19);
const int _G = 3;
const int _iG = 332748118;
const int inv2 = 499122177;
ll fpow(ll a, ll b, ll p) {
ll r = 1;
for (; b; a = a * a % p, b >>= 1) if (b & 1) r = r * a % p;
return r;
}
int rev[N], rev_n;
void prerev(int n) {
if (n == rev_n) return;
rev_n = n;
for (int i = 0; i < n; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
}
// NTT : fg=1 DFT fg=-1 IDFT
void NTT(ll f[], int n, int fg) {
prerev(n);
for (int i = 0; i < n; ++i) if (i < rev[i]) swap(f[i], f[rev[i]]);
for (int h = 2; h <= n; h <<= 1) {
ll Dt = fpow((fg == 1) ? _G : _iG, (mod - 1) / h, mod), w;
int len = h >> 1;
for (int j = 0; j < n; j += h) {
w = 1;
for (int k = j; k < j + len; ++k) {
ll tmp = MOD(f[k + len] * w);
f[k + len] = f[k] - tmp; (f[k + len] < 0) &&(f[k + len] += mod);
f[k] = f[k] + tmp; (f[k] >= mod) &&(f[k] -= mod);
w = MOD(w * Dt);
}
}
}
if (fg == -1) {
ll invn = fpow(n, mod - 2, mod);
for (int i = 0; i < n; ++i) f[i] = MOD(f[i] * invn);
}
}
// f(x) = f*g(x) n = def f ; m = def g ; len = 最终长度(保留几位)
void p_mul(ll f[], ll g[], int n, int m, int len) {
static ll a[N], b[N];
int nn = 1 << (int)ceil(log2(n + m - 1));
clr(a, nn); clr(b, nn); cpy(a, f, n); cpy(b, g, m);
NTT(a, nn, 1); NTT(b, nn, 1);
for (int i = 0; i < nn; ++i) a[i] = MOD(a[i] * b[i]);
NTT(a, nn, -1);
for (int i = 0; i < len; ++i) f[i] = a[i];
}
// f(x) = g^-1(x) f(x) 为 g(x) 模 x^n 意义下的逆
void p_inv(ll g[], int n, ll f[]) {
static ll sav[N];
int nn = 1 << (int)ceil(log2(n));
clr(f, n * 2);
f[0] = fpow(g[0], mod - 2, mod);
for (int h = 2; h <= nn; h <<= 1) {
cpy(sav, g, h); clr(sav + h, h);
NTT(sav, h << 1, 1); NTT(f, h << 1, 1);
for (int i = 0; i < (h << 1); ++i)
f[i] = f[i] * (2ll - f[i] * sav[i] % mod + mod) % mod;
NTT(f, h << 1, -1); clr(f + h, h);
}
clr(f + n, nn * 2 - n);
}
// f^2(x) = g(x) f(x) 为 g(x) 模 x^n 意义下的开方
void p_sqrt(ll g[], int n, ll f[]) {
static ll sav[N], r[N];
int nn = 1 << (int)ceil(log2(n));
clr(f, n * 2); f[0] = 1; // g[0] should be 1 otherwise
for (int h = 2; h <= nn; h <<= 1) {
cpy(sav, g, h); clr(sav + h, h); p_inv(f, h, r);
NTT(sav, h << 1, 1); NTT(r, h << 1, 1);
for (int i = 0; i < (h << 1); ++i) sav[i] = MOD(sav[i] * r[i]);
NTT(sav, h << 1, -1);
for (int i = 0; i < h; ++i) f[i] = MOD((f[i] + sav[i]) * inv2);
clr(f + h, h);
}
clr(f + n, nn * 2 - n);
}
// f(x) = g(x) * q(x) + r(x) : q(x) 为商 r(x) 为余数
void p_div(ll f[], ll g[], int n, int m, ll q[], ll r[]) {
static ll sav1[N], sav2[N];
int nn;
for (nn = 1; nn < n - m + 1; nn <<= 1);
clr(sav1, nn); clr(sav2, nn); cpy(sav1, f, n); cpy(sav2, g, m);
reverse(sav1, sav1 + n); reverse(sav2, sav2 + m);
p_inv(sav2, n - m + 1, q); p_mul(q, sav1, n - m + 1, n, n - m + 1);
reverse(q, q + n - m + 1); cpy(r, g, m);
p_mul(r, q, m, n - m + 1, m - 1);
for (int i = 0; i < m - 1; ++i) r[i] = MOD(f[i] - r[i] + mod);
}
// 预处理乘法逆元
ll inv[N];
void Initinv(int n) {
inv[0] = inv[1] = 1;
for (int i = 2; i <= n; ++i) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
}
// 对 f(x) 进行积分 Initinv() first
void p_int(ll f[], int n) {
for (int i = n - 1; i; --i) f[i] = MOD(f[i - 1] * inv[i]);
f[0] = 0;
}
// 对 f(x) 进行求导
void p_der(ll f[], int n) {
for (int i = 1; i < n; ++i) f[i - 1] = MOD(f[i] * i);
f[n - 1] = 0;
}
// f(x) <- ln f(x) f[0] should be 1
void p_ln(ll f[], int n) {
static ll g[N];
p_inv(f, n, g); p_der(f, n);
p_mul(f, g, n, n, n + n);
p_int(f, n);
}
// f(x) <- exp f(x) (倍增版) f[0] should be 0
void p_exp(ll f[], int n) {
static ll g[N], sav[N];
clr(g, n * 2); clr(sav, n * 2); g[0] = 1;
for (int h = 2; h <= n; h <<= 1) {
cpy(sav, g, h); p_ln(sav, h);
for (int i = 0; i < h; ++i) sav[i] = MOD(f[i] - sav[i] + mod);
sav[0] = MOD(sav[0] + 1);
p_mul(g, sav, h, h, h);
}
cpy(f, g, n);
}
/*
void _p_exp(ll f[],ll g[],int l,int r) {
static ll A[N],B[N];
if(r-l==1) {if(l>0) f[l]=MOD(f[l]*fpow(l,mod-2,mod));return ;}
int mid=(l+r)>>1,len=mid-l;
_p_exp(f,g,l,mid);
cpy(A,f+l,len); clr(A+len,len); cpy(B,g,len<<1);
p_mul(A,B,len<<1,len<<1,len<<1);
for(int i=mid;i<r;++i) f[i]=MOD(f[i]+A[i-l]);
_p_exp(f,g,mid,r);
}
// f(x) <- exp f(x) (分治 FFT 版) f[0] should be 0
void p_exp(ll f[],int n) {
static ll g[N];
cpy(g,f,n); clr(f,n); f[0]=1;
for(int i=0;i<n;++i) g[i]=MOD(g[i]*i);
_p_exp(f,g,0,n);
}
*/
// f(x) <- f^k(x) f(x) 模 x^n 意义下的 k 次
void p_pow(ll f[], int n, ll k) {
p_ln(f, n);
for (int i = 0; i < n; ++i) f[i] = MOD(f[i] * k);
p_exp(f, n);
}
// 分治FFT [l,r) F[n] = sum(0<i<=n) F[n-i]G[i]
void DCFFT(ll f[], ll g[], int l, int r) {
static ll A[N], B[N];
if (r - l == 1) return ;
int mid = (l + r) >> 1, len = mid - l;
DCFFT(f, g, l, mid);
cpy(A, f + l, len); clr(A + len, len); cpy(B, g, len << 1);
p_mul(A, B, len << 1, len << 1, len << 1);
for (int i = mid; i < r; ++i) f[i] = MOD(f[i] + A[i - l]);
DCFFT(f, g, mid, r);
}
}
using namespace poly;
int main() {
return 0;
}
// AC 自动机,字符串多模式串匹配
#include <bits/stdc++.h>
using namespace std;
namespace ACAM {
const int MAX = 200010;
int tr[MAX][26], fail[MAX], sz;
int tag[MAX];
void init() {
memset(tr[0], 0, sizeof(tr[0]));
fail[0] = 0; sz = 0;
}
int newnode() {
++sz; fail[sz] = 0; memset(tr[sz], 0, sizeof(tr[sz]));
return sz;
}
int insert(string &s) {
int p = 0, c;
for (int i = 0; i < s.size(); ++i) {
c = s[i] - 'a';
if (tr[p][c] == 0) tr[p][c] = newnode();
p = tr[p][c];
}
return p;
}
void build() {
queue<int> q;
for (int i = 0; i < 26; ++i) {
if (tr[0][i]) q.push(tr[0][i]);
}
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = 0; i < 26; ++i) {
if (tr[u][i]) fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
else tr[u][i] = tr[fail[u]][i];
}
}
}
void query(string &s) {
int cur = 0, c;
for (int i = 0; i <= sz; ++i) tag[i] = 0;
for (int i = 0; i < s.size(); ++i) {
c = s[i] - 'a';
cur = tr[cur][c];
tag[cur]++;
}
}
void work() {
static int idg[MAX];
for (int i = 0; i <= sz; ++i) idg[i] = 0;
for (int i = 1; i <= sz; ++i) ++idg[fail[i]];
queue<int> q;
for (int i = 1; i <= sz; ++i) if (idg[i] == 0) q.push(i);
while (!q.empty()) {
int u = q.front(); q.pop();
if (!u) break;
tag[fail[u]] += tag[u];
if (--idg[fail[u]] == 0) q.push(fail[u]);
}
}
}
int n, ed[200005];
string P[200005], T;
int main() {
cin >> n;
ACAM::init();
for (int i = 0; i < n; ++i)
cin >> P[i], ed[i] = ACAM::insert(P[i]);
ACAM::build();
cin >> T;
ACAM::query(T);
ACAM::work();
for (int i = 0; i < n; ++i)
cout << ACAM::tag[ed[i]] << "\n";
return 0;
}
// EXSAM 广义后缀自动机
#include <bits/stdc++.h>
template<typename _Tp>
inline void read(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp, typename... Args>void read(_Tp &t, Args &... args) {read(t); read(args...);}
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int N = 1000010;
namespace EXSAM {
const int MAX = 2000010;
struct sta {
int len, link;
int nxt[26];
int &operator[](const int k) {return nxt[k];}
} st[MAX];
int sz;
void init() {
sz = 1; st[0].link = -1;
}
void _extend(int last, int c) {
int cur = st[last][c], p = st[last].link; st[cur].len = st[last].len + 1;
while (p != -1 && st[p][c] == 0) {
st[p][c] = cur; p = st[p].link;
}
if (p == -1) st[cur].link = 0;
else {
int q = st[p][c];
if (st[q].len == st[p].len + 1) st[cur].link = q;
else {
int cp = sz++; st[cp].len = st[p].len + 1; st[cp].link = st[q].link;
for (int i = 0; i < 26; ++i) st[cp][i] = (st[st[q][i]].len == 0) ? 0 : st[q][i];
st[cur].link = st[q].link = cp;
while (p != -1 && st[p][c] == q) {
st[p][c] = cp;
p = st[p].link;
}
}
}
}
void build() {
queue<P> q;
for (int i = 0; i < 26; ++i) if (st[0][i] != 0) q.push(P(0, i));
while (!q.empty()) {
P u = q.front(); q.pop();
_extend(u.first, u.second);
int o = st[u.first][u.second];
for (int i = 0; i < 26; ++i) if (st[o][i] != 0) q.push(P(o, i));
}
}
void insert(char *s, int len) {
int cur = 0;
for (int i = 0; i < len; ++i) {
if (st[cur][s[i] - 'a'] == 0) st[cur][s[i] - 'a'] = sz++;
cur = st[cur][s[i] - 'a'];
}
}
ll solve() {
ll r = 0;
for (int i = 1; i < sz; ++i) r += st[i].len - st[st[i].link].len;
return r;
}
}
int n; char s[N];
int main() {
read(n);
EXSAM::init();
for (int i = 1; i <= n; ++i) {
scanf("%s", s);
EXSAM::insert(s, strlen(s));
}
EXSAM::build();
printf("%lld\n", EXSAM::solve());
return 0;
}
// KMP
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
char P[N], T[N];
int nxt[N], f[N], n, m;
void getnxt() {
nxt[1] = 0;
for (int i = 2, j = 0; i <= m; ++i) {
while (j > 0 && P[i] != P[j + 1]) j = nxt[j];
if (P[i] == P[j + 1]) ++j;
nxt[i] = j;
}
}
void KMP() {
for (int i = 1, j = 0; i <= n; ++i) {
while (j > 0 && (j == m || T[i] != P[j + 1])) j = nxt[j];
if (T[i] == P[j + 1]) ++j;
f[i] = j;
}
}
int main() {
scanf("%s%s", T + 1, P + 1);
n = strlen(T + 1), m = strlen(P + 1);
getnxt();
KMP();
for (int i = 1; i <= n; ++i) if (f[i] == m) printf("%d\n", i - m + 1);
for (int i = 1; i <= m; ++i) printf("%d%c", nxt[i], " \n"[i == m]);
return 0;
}
/*
manachar 马拉车算法
--> 线性求最长回文串
Oi-wiki(Manacher) --> https://oi-wiki.org/string/manacher/
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1.2e7;
char s[N], str[N << 1];
int p[N << 1];
int manacher() {
int len = strlen(s), n = 0;
str[n++] = '$'; str[n++] = '#';
for (int i = 0; i < len; i++) str[n++] = s[i], str[n++] = '#'; str[n] = '\0';
int mr = 0, ans = 0, mid = 0;
for (int i = 1; i < n; i++) {
p[i] = i < mr ? min(p[2 * mid - i], mr - i) : 1;
while (str[i - p[i]] == str[i + p[i]]) p[i]++;
if (p[i] + i > mr) mr = p[i] + i, mid = i;
ans = max(ans, p[i]);
}
return ans - 1;
}
int main() {
scanf("%s", s);
printf("%d\n", manacher());
}
// 最小表示法
#include <bits/stdc++.h>
template<typename _Tp>
inline void read(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp, typename... Args>void read(_Tp &t, Args &... args) {read(t); read(args...);}
using namespace std;
typedef long long ll;
const int N = 300010;
int a[N], n;
int minstr(int s[], int n) {
int i = 0, j = 1, k = 0; // i,j 比较的两个循环串开头,k为当前相等长度
while (i < n && j < n && k < n) {
if (s[(i + k) % n] == s[(j + k) % n]) ++k;
else {
if (s[(i + k) % n] < s[(j + k) % n]) j += k + 1;
else i += k + 1;
// 若 s[i..k-1] == s[j..k-1] ,s[i+k]<s[j+k] 说明 j~j+k 都不可能成为最小循环串,
// 因为都有对应的 i~i+k 比其更小
if (i == j) ++j;
k = 0;
}
}
return min(i, j);
}
int main() {
read(n);
for (int i = 0; i < n; ++i) read(a[i]);
int ps = minstr(a, n);
printf("%d", a[ps]);
for (int i = (ps + 1) % n; i != ps; i = (i + 1) % n) printf(" %d", a[i]);
puts("");
return 0;
}
/*
PAM 回文自动机 / 回文树
luogu P5496 【模板】回文自动机(PAM)
Oi-wiki --> https://oi-wiki.org/string/pam/
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
namespace PAM {
int sz, tot, lst; // sz:状态数量 tot:字符串长度 lst:上次状态
int cnt[N], sum[N], ch[N][26], len[N], fail[N]; // cnt:该状态对应原串中出现次数
// fail 指针跳到该串最长后缀回文,sum 记录跳几次跳完
char s[N];
int newnode(int l) {
++sz; memset(ch[sz], 0, sizeof(ch[sz]));
len[sz] = l; fail[sz] = cnt[sz] = sum[sz] = 0;
return sz;
}
void init() {
sz = -1; lst = 0; s[tot = 0] = '$';
newnode(0); newnode(-1); fail[0] = 1;
}
int getfail(int x) {
while (s[tot - len[x] - 1] != s[tot]) x = fail[x];
return x;
}
void insert(char c) {
s[++tot] = c;
int cur = getfail(lst);
if (!ch[cur][c - 'a']) {
int now = newnode(len[cur] + 2);
fail[now] = ch[getfail(fail[cur])][c - 'a'];
ch[cur][c - 'a'] = now;
sum[now] = sum[fail[now]] + 1;
}
++cnt[lst];
lst = ch[cur][c - 'a'];
}
void calc() {for (int i = sz; i >= 0; --i) cnt[fail[i]] += cnt[i];} // 计算每个状态出现次数
}
char str[N];
int k;
int main() {
scanf("%s", str);
PAM::init();
for (char *ps = str; *ps; ++ps) {
*ps = (*ps - 97 + k) % 26 + 97;
PAM::insert(*ps);
k = PAM::sum[PAM::lst]; // 以 ps 位为结尾的回文串数量
printf("%d ", k);
}
printf("\n");
return 0;
}
/*
后缀数组 (SA)
O(nlogn) 倍增做法,外加求 height 数组
Oi-wiki(后缀数组 ) --> https://oi-wiki.org/string/sa/
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
typedef long long ll;
int x[N], y[N], sa[N], c[N], rk[N], height[N];
char s[N];
int n, m;
void getSA() {
for (int i = 1; i <= n; ++i) ++c[x[i] = s[i]];
for (int i = 2; i <= m; ++i) c[i] += c[i - 1];
for (int i = n; i >= 1; --i) sa[c[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1) {
int num = 0;
for (int i = n - k + 1; i <= n; ++i) y[++num] = i;
for (int i = 1; i <= n; ++i) if (sa[i] > k) y[++num] = sa[i] - k;
for (int i = 1; i <= m; ++i) c[i] = 0;
for (int i = 1; i <= n; ++i) ++c[x[i]];
for (int i = 2; i <= m; ++i) c[i] += c[i - 1];
for (int i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i], y[i] = 0;
swap(x, y);
x[sa[1]] = 1; num = 1;
for (int i = 2; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num;
if (num == n) break;
m = num;
}
}
void getheight() {
int k = 0;
for (int i = 1; i <= n; ++i) rk[sa[i]] = i;
for (int i = 1; i <= n; ++i)if (rk[i] != 1) {
if (k > 0) --k;
int j = sa[rk[i] - 1];
while (j + k <= n && i + k <= n && s[i + k] == s[j + k]) ++k;
height[rk[i]] = k;
}
}
int main() {
scanf("%s", s + 1);
n = strlen(s + 1); m = 'z';
getSA();
// getheight();
for (int i = 1; i <= n; ++i)
printf("%d ", sa[i]);
printf("\n");
}
// SAM 后缀自动机
#include <bits/stdc++.h>
template<typename _Tp>
inline void read(_Tp &x) {
x = 0; bool fg = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fg ^= 1; ch = getchar();}
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp, typename... Args>void read(_Tp &t, Args &... args) {read(t); read(args...);}
using namespace std;
typedef long long ll;
const int N = 2000010;
char s[N]; int n;
namespace SAM {
struct sta {
int len, link;
int nxt[26];
};
const int MAX = 2000010;
sta st[MAX];
int ct[MAX], deg[MAX];
int sz, lst;
void init() {
sz = 1; st[0].len = 0; st[0].link = -1; lst = 0;
}
void extend(char c) {
int cur = sz++, p = lst; st[cur].len = st[lst].len + 1;
ct[cur]++;
while (p != -1 && !st[p].nxt[c - 'a']) {
st[p].nxt[c - 'a'] = cur;
p = st[p].link;
}
if (p == -1) st[cur].link = 0;
else {
int q = st[p].nxt[c - 'a'];
if (st[q].len == st[p].len + 1)
st[cur].link = q;
else {
int cp = sz++;
st[cp] = st[q];
st[cp].len = st[p].len + 1;
while (p != -1 && st[p].nxt[c - 'a'] == q) {
st[p].nxt[c - 'a'] = cp;
p = st[p].link;
}
st[cur].link = st[q].link = cp;
}
}
lst = cur;
}
void solve() {
for (int i = 1; i < sz; ++i)
deg[st[i].link]++;
queue<int> q;
for (int i = 1; i < sz; ++i) {
if (deg[i] == 0) q.push(i);
}
while (!q.empty()) {
int u = q.front(), f = st[u].link; q.pop();
if (f != -1) {
deg[f]--; ct[f] += ct[u];
if (deg[f] == 0) q.push(f);
}
}
ll ans = 0;
for (int i = 1; i < sz; ++i) {
if (ct[i] > 1)
ans = max(ans, (ll)ct[i] * st[i].len);
}
printf("%lld\n", ans);
}
}
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
SAM::init();
for (int i = 1; i <= n; ++i) SAM::extend(s[i]);
SAM::solve();
return 0;
}
#include <iostream>
using namespace std;
#define fi first
#define se second
typedef long long ll;
typedef pair<ll, ll> pll;
const int p1 = 1019260817; // 双模 hash
const int p2 = 1019260819;
const int bs = 125641; // 基数
const int N = 100000;
pll operator*(const pll &a, const ll &b) {return pll(a.fi * b % p1, a.se * b % p2);}
pll operator*(const pll &a, const pll &b) {return pll(a.fi * b.fi % p1, a.se * b.se % p2);}
pll operator+(const pll &a, const ll &b) {return pll((a.fi + b) % p1, (a.se + b) % p2);}
pll operator-(const pll &a, const pll &b) {return pll((a.fi - b.fi + p1) % p1, (a.se - b.se + p2) % p2);}
pll operator+(const pll &a, const pll &b) {return pll((a.fi + b.fi) % p1, (a.se + b.se) % p2);}
pll pw[N], pws[N]; // pw[i] = bs ^ i, pws[i] = \sum_{j=0}^i bs^j
void init(int n) {
pw[0] = {1, 1};
for (int i = 1; i <= n; ++i) pw[i] = pw[i - 1] * bs;
// pws[0] = {1, 1};
// for (int i = 1; i <= n; ++i) pws[i] = pws[i - 1] + pw[i];
}
// ---------- 用于线段树维护 Hash ----------
struct dat {
pll f; // 哈希值
int len; // 串长
dat() { f = {0, 0}; len = 0; }
dat(const pll &_f, const int &_len) { f = _f; len = _len; }
};
dat operator*(const dat &a, const dat &b) { // hash 值拼接
return dat(a.f * pw[b.len] + b.f, a.len + b.len);
}
// ---------- 字符串 Hash ----------
void initstr(char *S, int n, pll *f) {
f[0] = pll(0, 0); init(n);
for (int i = 1; i <= n; ++i)
f[i] = f[i - 1] * bs + (S[i] - 'a');
}
pll gethash(pll *f, int l, int r) {
return f[r] - f[l - 1] * pw[r - l + 1];
}
// Z 函数 (EXKMP)
#include <bits/stdc++.h>
using namespace std;
const int N = 40000010;
char s[N], t[N]; int z[N], n, m;
void Z_algo(char *s, int n) {
for (int i = 1; i <= n; ++i) z[i] = 0;
for (int i = 2, l = 0, r = 0; i <= n; ++i) {
if (i <= r) z[i] = min(z[i - l + 1], r - i + 1);
while (i + z[i] <= n && s[z[i] + 1] == s[i + z[i]]) ++z[i];
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
}
int main() {
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1), m = strlen(t + 1);
t[m + 1] = '@';
strcat(t + 1, s + 1);
Z_algo(t, n + m + 1);
return 0;
}