https://www.luogu.org/problemnew/show/P3960
如果 x = 1,相当于维护一条链,每次取出第 k 个数放在序列末尾
假设有 n + m + q 个位置,每个位置有数为 1 ,没有数为 0,
取出后不前移,那么第 k 个数就是第 k 个 1 的位置
初始时 1 ~ n + m - 1 为 1,其他位置为 0,
用线段树维护区间和即可
类似对于这道题把每行看做一条链,最后一列看做一条链
一次操作可以看成对两条链的操作
套用上面的方法即可
注意要动态开点
#include <bits/stdc++.h> using namespace std; const int N = 3e5 + 10; int n, m, Q, N_; int size[N * 20], lson[N * 20], rson[N * 20]; int root[N], jdjs; int ins[N]; int now_root; #define LL long long LL val[N * 20]; LL Ans1; #define gc getchar() inline int read() { int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x; } int Calc_size(int l, int r) { if(now_root != n + 1) { if(r <= m - 1) return r - l + 1; else { if(l <= m - 1) return (m - 1) - l + 1; else return 0; } } else { if(r <= n) return r - l + 1; else { if(l <= n) return n - l + 1; else return 0; } } } void Sec_A(int l, int r, int & jd, int x) { if(!jd) { jd = ++ jdjs; size[jd] = Calc_size(l, r); if(l == r) { if(now_root <= n) val[jd] = (LL) 1ll * (now_root - 1) * m + l; else val[jd] = (LL) 1ll * l * m; } } size[jd] --; if(l == r) {Ans1 = val[jd]; return ;} int mid = (l + r) >> 1; if((!lson[jd] && x <= mid - l + 1) || x <= size[lson[jd]]) Sec_A(l, mid, lson[jd], x); else { if(!lson[jd]) x -= (mid - l + 1); else x -= size[lson[jd]]; Sec_A(mid + 1, r, rson[jd], x); } } void Ins(int l, int r, int & jd, int whe, LL Num) { if(!jd) { jd = ++ jdjs; size[jd] = Calc_size(l, r); if(l == r) val[jd] = Num; } size[jd] ++; if(l == r) return ; int mid = (l + r) >> 1; if(whe <= mid) Ins(l, mid, lson[jd], whe, Num); else Ins(mid + 1, r, rson[jd], whe, Num); } int main() { n = read(), m = read(), Q = read(); N_ = max(n, m) + Q; while(Q --) { int x = read(), y = read(); if(y == m) now_root = n + 1, Sec_A(1, N_, root[now_root],x); else now_root = x, Sec_A(1, N_, root[now_root], y); cout << Ans1 << endl; now_root = n + 1; Ins(1, N_, root[n + 1], n + (++ ins[n + 1]), Ans1); if(y != m) { now_root = n + 1; Sec_A(1, N_, root[now_root], x); now_root = x; Ins(1, N_, root[x], m - 1 + (++ ins[x]), Ans1); } } return 0; }