noip 2017 列隊 (45行!!!!)
阿新 • • 發佈:2018-12-12
這題在仔細思考(看題解)後感覺還是挺簡單的。
因為對於每一次操作只會影響當前行和最後一列,那麼我們可以用動態開點線段樹來維護每一行的前m - 1 個然後在用一個維護最後一列,那麼就可以很愉快的A了。
程式碼(45行有木有!!!!)
#include<bits/stdc++.h> #define ll long long #define N 4600005 using namespace std; int ch[N][2], root[N], del[N], tot, n, m, q, M; vector<ll> extral[N]; int find(int l, int r, int rt, int x){ // 找當前位置 if(l == r) return l; int mid = (l + r) >> 1, ret = mid - l + 1 - del[ch[rt][0]]; if(ret >= x) return find(l, mid, ch[rt][0], x); else return find(mid + 1, r, ch[rt][1], x - ret); } void dele(int l, int r, int &rt, int x){ // 刪掉當前點 if(!rt) rt = ++ tot; del[rt] ++; if(l == r) return; int mid = (l + r) >> 1; if(x <= mid) dele(l, mid, ch[rt][0], x); else dele(mid + 1, r, ch[rt][1], x); } ll DL(int x, ll val){ // 刪掉最後一行的某一個點並把val 加進去 int pos = find(1, M, root[n + 1], x); ll ans; dele(1, M, root[n + 1], pos); if(pos <= n) ans = (ll)pos * m; else ans = extral[n + 1][pos - n - 1]; extral[n + 1].push_back(val?val:ans); return ans; } ll query(int x, int y){ // 處理非最後一行的情況 int pos = find(1, M, root[x], y); ll ans; dele(1, M, root[x], pos); if(pos < m) ans = (ll)(x - 1) * m + pos; else ans = extral[x][pos - m]; extral[x].push_back(DL(x, ans)); return ans; } int main(){ scanf("%d%d%d", &n, &m, &q); M = max(n, m) + q; for(;q --;){ int x, y; scanf("%d%d", &x, &y); if(y != m) printf("%lld\n", query(x, y)); else printf("%lld\n", DL(x, 0)); } return 0; }//呵呵呵呵呵呵呵呵呵呵呵
注意一下陣列要開大一些(log),不然會涼涼。
嘿嘿嘿嘿嘿嘿嘿嘿。
哈哈哈哈哈哈哈哈嗝。