请求开大时限
查看原帖
请求开大时限
119884
damocris楼主2020/7/5 17:29

目前能过的做法都是离线的,难道这个题强制离线吗? 我的主席树在线做法TLE了#8,#9, #10三个点。 https://www.luogu.com.cn/record/34870857

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

#define LOCAL 0
#define CONFIG_USE_PERSISTENT_SEGMENTTREE 1
#define CONFIG_USE_BITTREE 0 //offline
#define MAXN 1000000
#define MAXM 1000000

int32_t digits[MAXN+1];
int32_t buffer[MAXN+1];

#if CONFIG_USE_PERSISTENT_SEGMENTTREE 
struct SegmentNode {
  int32_t sum;
  uint32_t lc;
  uint32_t rc;
};

int last[MAXN+1];
SegmentNode tree[MAXN*22+1];
uint32_t roots[MAXN+1];
int id = 0;

//interval [low, high)
uint32_t PersistentSegmentTreeBuild(int low, int high)
{
  uint32_t root = ++id;
  tree[root].sum = 0;
  if (low+1==high) {
    tree[root].lc = 0;
    tree[root].rc = 0;
  } else {
    int mid = (low+high)/2;
    tree[root].lc = PersistentSegmentTreeBuild(low, mid);
    tree[root].rc = PersistentSegmentTreeBuild(mid, high);
  }
  return root;
}

//interval [low, high)
uint32_t PersistentSegmentTreeAdd(uint32_t index, int low, int high, int key)
{
  uint32_t idx = ++id;
  tree[idx].sum = tree[index].sum + 1;
  if (low+1==high) {
    tree[idx].lc = 0;
    tree[idx].rc = 0;
  } else {
    int mid = (low+high)/2;
    if (key < mid) {
      tree[idx].rc = tree[index].rc;
      tree[idx].lc = PersistentSegmentTreeAdd(tree[index].lc, low, mid, key);
    } else {
      tree[idx].lc = tree[index].lc;
      tree[idx].rc = PersistentSegmentTreeAdd(tree[index].rc, mid, high, key);
    }
  }
  return idx;
}

//[left, right) interval
uint32_t RangeRank(int total, int left, int right, int key)
{
  uint32_t rank = 0;
  int lroot, rroot;
  int low, high, mid;
  lroot = roots[left];
  rroot = roots[right];
  low = 0;
  high = total;
  while (low+1 != high) {
    mid = (low+high)/2;
    if (key < mid) {
      lroot = tree[lroot].lc;
      rroot = tree[rroot].lc;
      high = mid;
    } else {
      rank += tree[tree[rroot].lc].sum - tree[tree[lroot].lc].sum;
      lroot = tree[lroot].rc;
      rroot = tree[rroot].rc;
      low = mid;
    }
  }
  return rank;
}
#endif

int ReadInteger(void)
{
  int x=0, sign=1;
  int ch;
  ch = getchar();
  while (ch<'0' || ch>'9') {
    if (ch=='-') {
      sign = -1;
    }
    ch = getchar();
  }
  while (ch>='0' && ch<='9') {
    x = x*10 + ch-'0';
    ch = getchar();
  }
  return x*sign;
}

int main(void)
{
#if LOCAL
  freopen("test.in", "r", stdin);
  freopen("test.out", "w", stdout);
#endif
  int n, m;
  int left, right;
  int total;
  n = ReadInteger();
  digits[0] = 0;
  for (int i=1; i<=n; ++i) {
    digits[i] = ReadInteger();
  }
  memcpy(buffer, digits, (1+n)*sizeof(digits[0]));
  sort(buffer+1, buffer+n+1);
  total = unique(buffer+1, buffer+n+1)-(buffer+1);
  for (int i=1; i<=n; ++i) {
    digits[i] = lower_bound(buffer+1, buffer+total+1, digits[i]) - (buffer+1);  //index starts from 0
  }
  memset(buffer, 0, total*sizeof(buffer[0]));
  m = ReadInteger();
#if CONFIG_USE_PERSISTENT_SEGMENTTREE
  uint32_t rank;
  for (int i=1; i<=n; ++i) {
    if (buffer[digits[i]] == 0) {
      last[i] = 0;
    } else {
      last[i] = buffer[digits[i]];
    }
    buffer[digits[i]] = i;
  }
  roots[0] = PersistentSegmentTreeBuild(0, n);
  for (int i=1; i<=n; ++i) {
    roots[i] = PersistentSegmentTreeAdd(roots[i-1], 0, n, last[i]);
  }
  for (int i=0; i<m; ++i) {
    left = ReadInteger();
    --left;   //index starts from 0
    right = ReadInteger();
    rank = RangeRank(n, left, right, left+1);
    printf("%d\n", rank); 
  }
#endif
  return 0;
}
2020/7/5 17:29
加载中...