zoukankan      html  css  js  c++  java
  • 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;
    } 
    
    
  • 相关阅读:
    pat00-自测5. Shuffling Machine (20)
    Spiral Matrix
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Best Time to Buy and Sell Stock II
    4Sum
    3Sum Closest
    3Sum
    MySQL存储过程、函数和游标
    Word Ladder
  • 原文地址:https://www.cnblogs.com/BunnyLutts/p/13922928.html
Copyright © 2011-2022 走看看