# A Portal

f [ i ] [ p ] f[i][p] 表示当前已经完成了前i个任务，当前正在 a [ i ] a[i] 上，传送门的位置在 p p
•可以证明，只需要3种转移，就可以覆盖所有情况：
•1.直接从a[i]走到a[i+1]
•2.枚举走到a[i+1]之后，传送门的位置变为了哪个节点，设这个节点是q。第二种转移是从a[i]走到 q，在q设置传送门，从q传送到 p p ，再从 p p 走到 a [ i + 1 ] a[i + 1]
•3.第三种转移是从 a [ i ] a[i] 传送到 p p ，从 p p 走到 q q ，在 q q 设置传送门，最后从 q q 走到 a [ i + 1 ] a[i + 1]
•复杂度为 O ( k n 2 ) O(kn^2)

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
const int MAXN = 305;
const LL INF = 2e18;
inline void io()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
}
LL f[MAXN][MAXN];
LL d[MAXN][MAXN];
int a[MAXN * 2];
int main()
{
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
memset(d, 0x16, sizeof(d));
memset(f, 0x16, sizeof(f));
// cout << "d = " << d[1][2] << '\n';
for (int i = 1; i <= n; i++)
d[i][i] = 0;
for (int i = 1; i <= m; i++)
{
int u, v;
LL w;
scanf("%d %d %lld", &u, &v, &w);
d[u][v] = d[v][u] = min(d[u][v], w);
}

for (int k = 1; k <= n; k++)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
// if (i == j || k == i || k == j)
//     continue;
d[i][j] = d[j][i] = min(d[i][j], d[i][k] + d[k][j]);
}
}
// for (int i = 1; i <= n; i++)
// {
//     for (int j = 1; j <= n; j++)
//     {
//         if (d[i][j] != INF)
//             cout << "i = " << i << " j = " << j << " dpij = " << d[i][j] << "\n";
//     }
// }
for (int i = 1; i <= n; i++)
f[1][i] = d[1][i];
a[1] = 1;
for (int i = 1; i <= k; i++)
{
scanf("%d %d", &a[i * 2], &a[i * 2 + 1]);
}
for (int i = 2; i <= 2 * k + 1; i++)
{
for (int p = 1; p <= n; p++)
{
f[i][p] = min(f[i][p], f[i - 1][p] + d[a[i - 1]][a[i]]);
for (int q = 1; q <= n; q++)
{
f[i][q] = min(f[i][q], f[i - 1][p] + d[p][q] + d[q][a[i]]);
f[i][q] = min(f[i][q], f[i - 1][p] + d[a[i - 1]][q] + d[p][a[i]]);
}
}
}
LL ans = f[2 * k + 1][1];
for (int i = 1; i <= n; i++)
{
ans = min(ans, f[2 * k + 1][i]);
}
printf("%lld", ans);
// int t;
// cin >> t;
}


# H Interval

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
const int MAXN = 1e5 + 5;
inline void io()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
}
namespace Chairman
{
const int N = 1e5 + 5;
int ls[N * 300], rs[N * 300], rt[N], sum[N * 300], tot;
void update(int l, int r, int root, int last, int p, int v)
{
ls[root] = ls[last];
rs[root] = rs[last];
sum[root] = sum[last] + v;
if (l == r)
return;
int mid = l + r >> 1;
if (mid >= p)
update(l, mid, ls[root] = ++tot, ls[last], p, v);
else
update(mid + 1, r, rs[root] = ++tot, rs[last], p, v);
}
int query(int l, int r, int root, int ql, int qr)
{
if (l >= ql && r <= qr)
return sum[root];
int mid = l + r >> 1;
int ans = 0;
if (mid >= ql)
ans = query(l, mid, ls[root], ql, qr);
if (mid < qr)
ans += query(mid + 1, r, rs[root], ql, qr);
return ans;
}
}; // namespace Chairman
namespace Segtree
{
const int MAXN = 1e5 + 5;
struct node
{
int l, r;
LL sum, lazy;
} tree[MAXN << 2];
LL a[MAXN]; //you can put the num to this first
inline void build(int i, int l, int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].lazy = 0;
if (l == r)
{
tree[i].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(i * 2, l, mid);
build(i * 2 + 1, mid + 1, r);
tree[i].sum = tree[i * 2].sum & tree[i * 2 + 1].sum;
}
inline LL search(int i, int l, int r)
{
if (tree[i].l >= l && tree[i].r <= r)
{
return tree[i].sum;
}
if (tree[i].r < l || tree[i].l > r)
return 0;
LL ans = (1 << 30) - 1;
if (tree[i * 2].r >= l)
ans &= search(i * 2, l, r);
if (tree[i * 2 + 1].l <= r)
ans &= search(i * 2 + 1, l, r);
return ans;
}
} // namespace Segtree
int a[MAXN];
map<int, int> pre;
int main()
{

// Chairman::tot = 0;
// Chairman::rt[0] = 0;
// Chairman::update(1, 10, Chairman::rt[1] = ++Chairman::tot, Chairman::rt[0], 3, 1);
// Chairman::update(1, 10, Chairman::rt[2] = ++Chairman::tot, Chairman::rt[1], 1, -1);
// Chairman::update(1, 10, Chairman::rt[3] = ++Chairman::tot, Chairman::rt[2], 6, 2);
// cout << Chairman::query(1, 10, Chairman::rt[1],1,3) << '\n';
// cout << Chairman::query(1, 10, Chairman::rt[3],3,6) << '\n';
// cout << Chairman::query(1, 10, Chairman::rt[3],1,6) << '\n';

int n;
// cin >> n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
// cin >> a[i];
scanf("%d", &a[i]);
Segtree::a[i] = a[i];
}
Segtree::build(1, 1, n);
Chairman::tot = 0;
Chairman::rt[0] = 0;
for (int i = 1; i <= n; i++)
{
if (pre.find(a[i]) != pre.end())
{
// int nowrt = Chairman::tot;
Chairman::update(1, n, Chairman::rt[i] = ++Chairman::tot, Chairman::rt[i - 1], pre[a[i]], -1);
int now = ++Chairman::tot;
Chairman::update(1, n, now, Chairman::rt[i], i, 1);
Chairman::rt[i] = now;
}
else
Chairman::update(1, n, Chairman::rt[i] = ++Chairman::tot, Chairman::rt[i - 1], i, 1);
pre[a[i]] = i;
int v = a[i], p = i;
for (int j = 30; j; j--)
{
int l = 1, r = p - 1;
int ans = 0;
while (l <= r)
{
int mid = (l + r) >> 1;
if (Segtree::search(1, mid, i) < v)
l = mid + 1, ans = mid;
else
{
r = mid - 1;
}
}
if (ans == 0)
break;
v = Segtree::search(1, ans, i);
p = ans;
int now;
if (pre.find(v) != pre.end())
{
now = ++Chairman::tot;
Chairman::update(1, n, now, Chairman::rt[i], pre[v], -1);
Chairman::rt[i] = now;
}
now = ++Chairman::tot;
Chairman::update(1, n, now, Chairman::rt[i], p, 1);
Chairman::rt[i] = now;
pre[v] = p;
}
}
int Q;
scanf("%d", &Q);
int lastans = 0;
while (Q--)
{
int L, R;
scanf("%d %d", &L, &R);
L = (L ^ lastans) % n + 1;
R = (R ^ lastans) % n + 1;
if (L > R)
swap(L, R);
lastans = Chairman::query(1, n, Chairman::rt[R], L, R);
printf("%d\n", lastans);
}
// int t;
// cin >> t;
}