Description
有一序列 aaa,长度为 nnn。
还有一个长度为 mmm 的操作序列 bbb,每个操作形如:
- swap(x,y)\operatorname{swap}(x,y)swap(x,y):交换 axa_xax 和 aya_yay.
- assign(l,r,k)\operatorname{assign}(l,r,k)assign(l,r,k):对每个 i∈[l,r]i \in [l,r]i∈[l,r] 执行 ai←ka_i \gets kai←k.
- get(p)\operatorname{get}(p)get(p):求 apa_pap 的值.
现在有 qqq 个查询,每次给定一个二元组 (L,R)(L,R)(L,R),执行下面操作:
- 将 aaa 每一项设为 000.
- 执行操作 bL,bL+1,⋯ ,bRb_L,b_{L+1},\cdots,b_RbL,bL+1,⋯,bR.
- 输出所有 get\operatorname{get}get 操作的答案之和.
Limitations
1≤n,m,q≤1061 \le n,m,q \le 10^61≤n,m,q≤106
1≤k≤1091 \le k \le 10^91≤k≤109
1≤x,y≤n1 \le x,y \le n1≤x,y≤n
1≤l≤r≤n1 \le l \le r \le n1≤l≤r≤n
1≤L≤R≤m1 \le L \le R \le m1≤L≤R≤m
1s,512MB1\text{s},512\text{MB}1s,512MB
Solution
使用线段树维护区间最后一次 assign\operatorname{assign}assign 的时刻,遇到 get\operatorname{get}get 时,查询 ppp 点的值并记为 tit_iti.
考虑将询问挂在 rrr 上做扫描线,遇到 get\operatorname{get}get 时,在 tit_iti 位置加上第 tit_iti 次操作的 kkk,对每个询问查询 [l,r][l,r][l,r] 的和,可以用树状数组.
然后卡卡常数,需要用快读.
Code
4.52KB,4.07s,119.21MB (in total, C++ 20 with O2)4.52\text{KB},4.07\text{s},119.21\text{MB}\;\texttt{(in total, C++ 20 with O2)}4.52KB,4.07s,119.21MB(in total, C++ 20 with O2)
模板已删.
// Problem: P5524 [Ynoi2012] NOIP2015 充满了希望
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5524
// Memory Limit: 512 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;
template<class T>
bool chmax(T &a, const T &b){
if(a < b){ a = b; return true; }
return false;
}
template<class T>
bool chmin(T &a, const T &b){
if(a > b){ a = b; return true; }
return false;
}
namespace fastio {}
using fastio::read;
using fastio::write;
inline int lowbit(int x) {
return x & -x;
}
template<class T>
struct fenwick {};
inline int ls(int u) { return 2 * u + 1; }
inline int rs(int u) { return 2 * u + 2; }
struct SegTree {
struct Node {
int l, r, tag;
};
vector<Node> tr;
inline SegTree() {}
inline SegTree(int n) {
tr.resize(n << 2);
build(0, 0, n - 1);
}
inline void pushdown(int u) {
if (tr[u].tag != -1) {
tr[ls(u)].tag = tr[rs(u)].tag = tr[u].tag;
tr[u].tag = -1;
}
}
inline void build(int u, int l, int r) {
tr[u].l = l;
tr[u].r = r;
tr[u].tag = -1;
if (l == r) return;
const int mid = (l + r) >> 1;
build(ls(u), l, mid);
build(rs(u), mid + 1, r);
}
inline void assign(int u, int l, int r, int x) {
if (l <= tr[u].l && tr[u].r <= r) {
tr[u].tag = x;
return;
}
const int mid = (tr[u].l + tr[u].r) >> 1;
pushdown(u);
if (l <= mid) assign(ls(u), l, r, x);
if (r > mid) assign(rs(u), l, r, x);
}
inline int get(int u, int p) {
if (tr[u].l == tr[u].r || tr[u].tag != -1) return tr[u].tag;
const int mid = (tr[u].l + tr[u].r) >> 1;
if (p <= mid) return get(ls(u), p);
else return get(rs(u), p);
}
};
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
const int n = read<int>(), m = read<int>(), q = read<int>();
vector<int> op(m), x(m), y(m), val(m);
SegTree sgt(n);
for (int i = 0; i < m; i++) {
op[i] = read<int>();
if (op[i] == 1) {
x[i] = read<int>(), y[i] = read<int>();
x[i]--, y[i]--;
int a = sgt.get(0, x[i]), b = sgt.get(0, y[i]);
sgt.assign(0, x[i], x[i], b);
sgt.assign(0, y[i], y[i], a);
}
else if (op[i] == 2) {
x[i] = read<int>(), y[i] = read<int>(), val[i] = read<int>();
x[i]--, y[i]--;
sgt.assign(0, x[i], y[i], i);
}
else {
x[i] = read<int>(), x[i]--;
y[i] = sgt.get(0, x[i]);
}
}
fenwick<i64> fwk(m);
vector<vector<pair<int, int>>> queries(m);
vector<i64> ans(q);
for (int i = 0, l, r; i < q; i++) {
l = read<int>(), r = read<int>();
l--, r--;
queries[r].emplace_back(l, i);
}
for (int i = 0; i < m; i++) {
if (op[i] == 3 && y[i] != -1) fwk.add(y[i], val[y[i]]);
for (auto [pos, id] : queries[i]) ans[id] = fwk.ask(pos, i);
}
for (const auto& i : ans) {
write(i);
putchar_unlocked('\n');
}
return 0;
}