• 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;
    } 
    
    
  • 相关阅读:
    软件需求与分析课堂讨论
    Axios
    lodash
    table行拖拽
    js addDays ,addYears
    所在周的第一天
    Inner join case when
    npm 淘宝镜像安装以及安装报错window_nt 6.1.7601 解决
    jsTree
    Bootstrap Multiselect
  • 原文地址:https://www.cnblogs.com/BunnyLutts/p/13922928.html
Copyright © 2020-2023  润新知