线段树并不支持动态的删除,常见的方法是提前预留位置,并维护区间内实际留存的个数($sz$)
对于这道题,维护$n+1$棵线段树,前$n$棵对应$n$行,第$n+1$棵对应最后一列,动态开点,便可维护
时间复杂度 $O(q*\log (m+q))$
空间复杂度 $O(q*\log (m+q))$
$sz$的维护采用的是标记永久化中的写法
还有一个比较重要的地方是新开的点的$sz$的维护
第一次打这种预留位置的题,很不熟悉
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #define ll long long 6 using namespace std; 7 8 template <typename T> void in(T &x) { 9 x = 0; T f = 1; char ch = getchar(); 10 while(!isdigit(ch)) {if(ch == ‘-‘) f = -1; ch = getchar();} 11 while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();} 12 x *= f; 13 } 14 15 template <typename T> void out(T x) { 16 if(x < 0) x = -x , putchar(‘-‘); 17 if(x > 9) out(x/10); 18 putchar(x%10 + 48); 19 } 20 //------------------------------------------------------------- 21 22 const int N = 3e5+7; 23 24 int n,m,q,x,y,now,maxn; 25 int end[N]; 26 27 struct node { 28 int lc,rc,sz;ll val; 29 }t[6000000];int cnt,rt[N]; 30 31 int get_sz(int l,int r) { 32 if(now == n + 1) { 33 if(r <= n) return r - l + 1; 34 if(l <= n) return n - l + 1; 35 return 0; 36 } 37 if(r <= m-1) return r - l + 1; 38 if(l <= m-1) return (m-1)-l+1; 39 return 0; 40 } 41 42 ll get_val(int j) { 43 return (now == n+1) ? (1ll*j*m) : (1ll*(now-1)*m+j); 44 } 45 46 ll D(int &u,int l,int r,int k) { 47 if(!u) { 48 u = ++cnt; t[u].sz = get_sz(l,r); 49 if(l == r) t[u].val = get_val(l); 50 } 51 --t[u].sz; 52 if(l == r) return t[u].val; 53 int mid = (l+r)>>1; 54 int l_sz = (t[u].lc ? t[t[u].lc].sz : get_sz(l,mid)); 55 if(k <= l_sz) return D(t[u].lc,l,mid,k); 56 else return D(t[u].rc,mid+1,r,k-l_sz); 57 } 58 59 void A(int &u,int l,int r,int pos,ll w) { 60 if(!u) { 61 u = ++cnt; 62 t[u].sz = get_sz(l,r); 63 } 64 ++t[u].sz;//标记永久化的写法 65 if(l == r) { 66 t[u].val = w; return; 67 } 68 int mid = (l+r)>>1; 69 if(pos <= mid) A(t[u].lc,l,mid,pos,w); 70 else A(t[u].rc,mid+1,r,pos,w); 71 } 72 73 int main() { 74 freopen("0.in","r",stdin); 75 //freopen("my19.out","w",stdout); 76 ll id; in(n); in(m); in(q);//debug ll -> int 77 maxn = max(m,n)+q;//debug max(m,n) -> m!!!!! 78 int ans = 0; 79 while(q--) { 80 in(x); in(y); 81 cout << ++ans << ‘:‘ << ‘ ‘; 82 if(y == m) { 83 now = n+1; id = D(rt[n+1],1,maxn,x); out(id),putchar(‘\n‘); 84 A(rt[n+1],1,maxn,n+(++end[n+1]),id); 85 } 86 else { 87 now = x; id = D(rt[x],1,maxn,y); out(id),putchar(‘\n‘); 88 now = n+1; A(rt[n+1],1,maxn,n+(++end[n+1]),id); 89 now = n+1; id = D(rt[n+1],1,maxn,x); 90 now = x; A(rt[x],1,maxn,m-1+(++end[x]),id); 91 } 92 } 93 return 0; 94 }
原文:https://www.cnblogs.com/mzg1805/p/11412672.html