LOJ2319. 「NOIP2017」列队【线段树】

LINK

思路

神仙线段树

你考虑怎么样才能快速维护出答案

首先看看一条链怎么做?

首先很显然的思路是维护每个节点的是否出过队

然后对于重新入队的点

直接在后面暴力vector存一下就可以了

最核心的思路就是假设你已经知道了当前位置的点是什么编号,最后通过计算/查询来得出答案

然后不是链的情况其实就动态开点就可以了

因为有用的状态很少

然后就直接进行查询就可以了


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
  bool w = 1;x = 0;
  char c = getchar();
  while (!isdigit(c) && c != '-') c = getchar();
  if (c == '-') w = 0, c = getchar();
  while (isdigit(c)) {
    x = (x<<1) + (x<<3) + c -'0';
    c = getchar();
  }
  if (!w) x = -x;
}
template <typename T>
void Write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x > 9) Write(x / 10);
  putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 3e5 + 10;
const int LOG = 40;
int tot = 0, n, m, q, p;
int rt[N], ls[N * LOG], rs[N * LOG], siz[N * LOG];
vector<ll> v[N];
void insert(int &t, int l, int r, int pos) {
  if (!t) t = ++tot;
  ++siz[t];
  if (l == r) return;
  int mid = (l + r) >> 1;
  if (pos <= mid) insert(ls[t], l, mid, pos);
  else insert(rs[t], mid + 1, r, pos);
}
int query(int t, int l, int r, int k) {
  if (l == r) return l;
  int mid = (l + r) >> 1, sizl = mid - l + 1 - siz[ls[t]];
  if (k <= sizl) return query(ls[t], l, mid, k);
  else return query(rs[t], mid + 1, r, k - sizl);
}
ll query_single_row(ll x, ll y) {
  ll res = query(rt[0], 1, p, x);
  insert(rt[0], 1, p, res);
  ll id = (res <= n) ? res * m : v[0][res - n - 1];
  v[0].push_back(y ? y : id);
  return id;
}
ll query_single_line(ll x, ll y) {
  ll res = query(rt[x], 1, p, y);
  insert(rt[x], 1, p, res);
  ll id = (res < m) ? (x - 1) * m + res : v[x][res - m];
  v[x].push_back(query_single_row(x, id));
  return id;
}
int main() {
#ifdef dream_maker
  freopen("input.txt", "r", stdin);
#endif
  Read(n), Read(m), Read(q);
  p = max(n, m) + q;
  fu(i, 1, q) {
    int x, y; Read(x), Read(y);
    if (y == m) Write(query_single_row(x, 0));
    else Write(query_single_line(x, y));
    putchar('\n');
  }
  return 0;
}
posted @ 2018-11-02 19:26  Dream_maker_yk  阅读(155)  评论(0编辑  收藏  举报