The 2023 ICPC Asia Hong Kong Regional Programming Contest E (线段树思维)

  • 我们可以一个数一个数考虑贡献 从前往后 如果说1-r 最小值为0 我们就加上贡献
#include 
/*#include 
#include 
#include 
#include 
#include 
#include 
#include 
*/

// 从a[r-1] 到 a[r]的变化 的贡献考虑就行  细节比较多
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb push_back
#define inf 1ll << 62
#define db double
#define endl "\n"
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(), a.end()
#define IOS                         \
  std::ios::sync_with_stdio(false); \
  cin.tie(0);                       \
  cout.tie(0);
#define fer(i, a, b) for (int i = a; i <= b; i++)
#define der(i, a, b) for (int i = a; i >= b; i--)
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int n, m, k;
struct node {
  int l, r;
  ll lz;
  ll sum;
  ll num;
#define ls i * 2
#define rs i * 2 + 1
} tr[N * 4];

node operator+(node a, node b) {
  node tmp;
  tmp.l = a.l;
  tmp.r = b.r;
  tmp.lz=0;
  if (a.num < b.num)
    tmp.num = a.num, tmp.sum = a.sum;
  else if (a.num > b.num)
    tmp.num = b.num, tmp.sum = b.sum;
  else
    tmp.num = a.num, tmp.sum = a.sum + b.sum;
  return tmp;
}

void build(int i, int l, int r) {
  tr[i] = {l, r,0,0,0};
  if (l == r) {
    tr[i] = {l, r, 0, 1, 0};
    return;
  }
  int mid = l + r >> 1;
  build(ls, l, mid);
  build(rs, mid + 1, r);
  tr[i] = tr[ls] + tr[rs];
}

void pushdown(int i) {
  if (tr[i].lz) {
    tr[ls].lz += tr[i].lz;
    tr[rs].lz += tr[i].lz;
    tr[ls].num += tr[i].lz;
    tr[rs].num += tr[i].lz;
    tr[i].lz = 0;
  }
}
void change(int i, int l, int r, int val) {
  if (l <= tr[i].l && tr[i].r <= r) {
    tr[i].num += val;
    tr[i].lz += val;
    return;
  }
  pushdown(i);
  int mid = (tr[i].l + tr[i].r) >> 1;
  if (l <= mid) change(ls, l, r, val);
  if (r > mid) change(rs, l, r, val);
  tr[i] = tr[ls] + tr[rs];
}

node query(int i, int l, int r) {
  if (l <= tr[i].l && tr[i].r <= r) return tr[i];
  pushdown(i);
  int mid = (tr[i].l + tr[i].r) >> 1;
  if (r <= mid)
    return query(ls, l, r);
  else if (l > mid)
    return query(rs, l, r);
  else
    return query(ls, l, r) + query(rs, l, r);
}
int a[N];
vector<int> p[N];
void solve() {
  cin >> n >> k;
  build(1, 1, n);
  for (int i = 1; i <= n; i++) cin >> a[i];
  ll ans = 0;
  for (int r = 1; r <= n; r++) {
    p[a[r]].push_back(r);
    int s = p[a[r]].size();
    if (s >= k) {
      int r1 = p[a[r]][s - k];
      int l1;
      if (s >=k+1) {
        l1 = p[a[r]][s - k - 1] + 1;
      } else
        l1 = 1;

      int r2 = l1 - 1;
      int l2;
      if (s >=k+2) {
        l2 = p[a[r]][s - k - 2] + 1;
      } else l2 = 1;
      change(1, l1, r1, 1);
      if (l2 <= r2) change(1, l2, r2, -1);
    //  cout << l1 << " " << r1 << " " << l2 << " " << r2 << endl;
    }
    
    node tmp = query(1, 1, r);
    //cout<
    //cout<
    if (tmp.num == 0) ans += tmp.sum;

  }
  cout << ans << endl;
}
int main() {
  IOS;
  int _ = 1;
  // cin>>_;
  while (_--) solve();
  return 0;
}

你可能感兴趣的:(数据结构,c++,算法)