GMOJ 6847 通往强者之路

可以发现一条递推式

[a_i=n-1+[a_{i-n}ge n]+[a_{i-n-1}=n+1] ]

那么我们把({n-1, n, n+1})分别标号为({0, 1, 2}),将(a_i)每n个排成一行,当上一行同一位置大于0时对该位置有1的贡献,当上一行前一位置大于1时对该位置有1的贡献。

为了方便边界条件,我们假想每一行末尾多出一个1,那么可以看作每向下一行就把高为2的砖向右平移,然后如果该位置为0就填补上去。

我们把每个坑被填补的时间计算出来,排序,模拟即可。

#define DEBUG
#include <cstdio>

using namespace std;

const int maxn=150000;

void swap(int &a, int &b) {
  int t;
  t=a, a=b, b=t;
}

int min(int a, int b) {
  return a<b ? a : b;
}

int max(int a, int b) {
  return a>b ? a : b;
}

class SegmentTree {
public:
  int a[4*maxn+1][6], v[4*maxn+1][6], mark[4*maxn+1], flag[4*maxn+1], p;

  void markDown(int o, int l, int r) {
    if (mark[o]) {
      if (flag[o]) {
        flag[o] = 0;
      }
      if (l!=r) {
        mark[o*2] = mark[o*2+1] = mark[o];
      }
      a[o][1] = mark[o], v[o][1] = r-l+1;
      for (int i=2; i<=p; i++) {
        a[o][i] = v[o][i] = 0;
      }
      mark[o] = 0;
    } else if (flag[o]) {
      if (l!=r) {
        if (mark[o*2]) {
          mark[o*2] += flag[o];
        } else {
          flag[o*2] += flag[o];
        }
        if (mark[o*2+1]) {
          mark[o*2+1] += flag[o];
        } else {
          flag[o*2+1] += flag[o];
        }
      }
      for (int i=1; i<=p; i++) {
        a[o][i]+=flag[o];
      }
      flag[o] = 0;
    }
  }

  void update(int a[], int v[], int a1[], int v1[], int a2[], int v2[]) {
    for (int i=1; i<=p; i++) {
      a[i]=v[i]=0;
    }
    int maxcnt=0;
    for (int i=1; i<=p; i++) {
      if (a1[i]) {
        int cnt=v1[i], t=a1[i];
        for (int j=1; j<=p; j++) {
          if (a2[j]==t) {
            cnt+=v2[j];
            break;
          }
        }
        for (int j=1; j<=p; j++) {
          if (v[j]<=cnt) {
            swap(a[j], t);
            swap(v[j], cnt);
          }
        }
        maxcnt = max(maxcnt, cnt);
      }
    }
    for (int i=1; i<=p; i++) {
      if (a2[i]) {
        int cnt=0, t=a2[i];
        for (int j=1; j<=p; j++) {
          if (a1[j]==t) {
            cnt = 1;
            break;
          }
        }
        if (!cnt) {
          cnt=v2[i];
          for (int j=1; j<=p; j++) {
            if (v[j]<=cnt) {
              swap(a[j], t);
              swap(v[j], cnt);
            }
          }
          maxcnt = max(maxcnt, cnt);
        }
      }
    }
    for (int i=1; i<=p; i++) {
      if (a[i]) {
        v[i]-=maxcnt;
      }
    }
  }

  void set(int o, int l, int r, int tl, int tr, int tv) {
    markDown(o, l, r);
    if (l==tl && r==tr) {
      mark[o] = tv;
      markDown(o, l, r);
    } else {
      int mid=(l+r)/2;
      if (tl<=mid) {
        set(o*2, l, mid, max(tl, l), min(tr, mid), tv);
      } else {
        markDown(o*2, l, mid);
      }
      if (tr>mid) {
        set(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), tv);
      } else {
        markDown(o*2+1, mid+1, r);
      }
      update(a[o], v[o], a[o*2], v[o*2], a[o*2+1], v[o*2+1]);
    }
  }

  void add(int o, int l, int r, int tl, int tr) {
    markDown(o, l, r);
    if (l==tl && r==tr) {
      flag[o]++;
      markDown(o, l, r);
    } else {
      int mid=(l+r)/2;
      if (tl<=mid) {
        add(o*2, l, mid, max(tl, l), min(tr, mid));
      } else {
        markDown(o*2, l, mid);
      }
      if (tr>mid) {
        add(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r));
      } else {
        markDown(o*2+1, mid+1, r);
      }
      update(a[o], v[o], a[o*2], v[o*2], a[o*2+1], v[o*2+1]);
    }
  }

  void get(int o, int l, int r, int tl, int tr, int ans[], int ansv[]) {
    markDown(o, l, r);
    if (l==tl && r==tr) {
      int temp[6], tempv[6];
      for (int i=1; i<=p; i++) {
        temp[i] = ans[i], tempv[i] = ansv[i];
      }
      update(ans, ansv, temp, tempv, a[o], v[o]);
    } else {
      int mid=(l+r)/2;
      if (tl<=mid) {
        get(o*2, l, mid, max(tl, l), min(tr, mid), ans, ansv);
      }
      if (tr>mid) {
        get(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), ans, ansv);
      }
    }
  }
};

int main() {
  freopen("war.in", "r", stdin);
  freopen("war.out", "w", stdout);

  static SegmentTree sgt;
  int n, m, p;
  scanf("%d %d %d", &n, &m, &p);
  sgt.p = 100/p;
  for (int i=1; i<=n; i++) {
    int a;
    scanf("%d", &a);
    sgt.set(1, 1, n, i, i, a);
  }

  for (int i=1; i<=m; i++) {
    int opt, l, r, id;
    scanf("%d %d %d", &opt, &l, &r);
    if (opt==1) {
      scanf("%d", &id);
      sgt.set(1, 1, n, l, r, id);
    } else if (opt==2) {
      sgt.add(1, 1, n, l, r);
    } else if (opt==3) {
      static int ans[6], ansv[6];
      for (int i=1; i<=sgt.p; i++) {
        ans[i]=ansv[i]=0;
      }
      sgt.get(1, 1, n, l, r, ans, ansv);
      int cnt=0;
      for (int i=1; i<=sgt.p; i++) {
        if (ans[i]) {
          cnt++;
        }
      }
      printf("%d ", cnt);
      for (int i=1; i<=cnt; i++) {
        printf("%d ", ans[i]);
      }
      printf("
");
    }
  }

  fclose(stdin);
  fclose(stdout);
  return 0;
} 

原文地址:https://www.cnblogs.com/BunnyLutts/p/13922928.html