NC54833. 重点班
描述
因为在上学期的期末考中取得了优异的成绩,小C进入了重点班。她发现她的很多同班同学对自己的成绩都有很高的要求。而一旦没有达到自己的目标,他们就会自闭,然后退出重点班。为了简化问题,我们做出如下假设:
1. 每个同学对自己的要求用一个正整数ai描述,表示考得比自己差的人不能少于(全班总人数-1)/ai。
2. 每次考试的成绩取决于每个人的能力值bi,能力值越大成绩越高(能力值相同则成绩相同)。
3. 每次考试后,所有没有达到自己要求的同学同时退出。
小C很想知道,每名同学会在第几次考试后退出。
输入描述
第1行包括一个正整数n,表示重点班的初始人数。
第2行到第n+1行,每行包括两个正整数ai,bi。
输出描述
对于每个人输出一行一个整数,表示Ta会在第几次考试后退出;如果Ta永远不会退出,输出0。
示例1
输入:
5 3 1 2 2 2 3 2 4 2 5
输出:
1 1 2 3 0
C++14(g++5.4) 解法, 执行用时: 753ms, 内存消耗: 17120K, 提交时间: 2020-01-17 22:15:59
#include <iostream> #include <algorithm> #include <vector> constexpr int N = 100'000, M = 1 << 18; int n; int t[M], min[M], ans[N], pm[N], a[N], b[N], bp[N]; std::vector<int> change[N], y; void add(int p, int v) { min[p] += v; t[p] += v; } void push(int p) { add(2 * p, t[p]); add(2 * p + 1, t[p]); t[p] = 0; } void rangeAdd(int p, int l, int r, int x, int y, int v) { if (l >= y || r <= x) return; if (l >= x && r <= y) return add(p, v); int m = (l + r) / 2; push(p); rangeAdd(2 * p, l, m, x, y, v); rangeAdd(2 * p + 1, m, r, x, y, v); min[p] = std::min(min[2 * p], min[2 * p + 1]); } void search(int p, int l, int r, int x) { if (min[p] >= 0) return; if (r - l == 1) { ans[pm[l]] = x; y.push_back(l); min[p] = 1'000'000'000; return; } int m = (l + r) / 2; push(p); search(2 * p, l, m, x); search(2 * p + 1, m, r, x); min[p] = std::min(min[2 * p], min[2 * p + 1]); } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cin >> n; for (int i = 0; i < n; ++i) std::cin >> a[i] >> b[i]; for (int i = 0; i < n; ++i) pm[i] = i; std::sort(pm, pm + n, [&](int i, int j) { return b[i] < b[j]; }); for (int i = 0; i < n; ++i) bp[i] = b[pm[i]]; for (int i = 0; i < n; ++i) { rangeAdd(1, 0, n, std::upper_bound(bp, bp + n, b[i]) - bp, n, 1); rangeAdd(1, 0, n, i, i + 1, -((n - 1 + a[pm[i]] - 1) / a[pm[i]])); if (a[pm[i]] == 1) continue; for (int j = 1; j < n; j += a[pm[i]]) change[j].push_back(i); } int max = 0, cnt = 0; for (int i = 0; i < n; ++i) { if (b[pm[i]] > max) { max = b[pm[i]]; cnt = 1; } else if (b[pm[i]] == max) { ++cnt; } } if (cnt == 1) for (int i = 0; i < n; ++i) if (b[pm[i]] == max) rangeAdd(1, 0, n, i, i + 1, 1'000'000'000); int lastn = n, tt = 0; while (true) { search(1, 0, n, ++tt); if (y.empty()) break; for (int i : y) rangeAdd(1, 0, n, std::upper_bound(bp, bp + n, b[pm[i]]) - bp, n, -1); for (int j = lastn - 1; j >= lastn - int(y.size()); --j) for (int i : change[j]) rangeAdd(1, 0, n, i, i + 1, 1); lastn -= y.size(); y.clear(); } for (int i = 0; i < n; ++i) std::cout << ans[i] << " \n"[i == n - 1]; return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 322ms, 内存消耗: 19712K, 提交时间: 2020-01-17 21:01:08
#include<bits/stdc++.h> using namespace std; template <typename T> void chmin(T&x,const T &y) { if(x>y)x=y; } template <typename T> void chmax(T &x,const T &y) { if(x<y)x=y; } typedef int64_t s64; typedef uint64_t u64; typedef uint32_t u32; typedef pair<int,int> pii; #define rep(i,l,r) for(int i=l;i<=r;++i) #define per(i,r,l) for(int i=r;i>=l;--i) #define rep0(i,l,r) for(int i=l;i<r;++i) #define gc (c=getchar()) char readc() { char c; while(gc<'-'); return c; } int read() { char c; while(gc<'-'); if(c=='-') { int x=gc-'0'; while(gc>='0')x=x*10+c-'0'; return -x; } int x=c-'0'; while(gc>='0')x=x*10+c-'0'; return x; } #undef gc const int N=1e5+5; int n,a[N],b[N],c[N],s[N],q[N],ndy[N],dy[N],dy1[N],h[N]; int mn[N*3],ad[N*3],d,ans[N]; vector<int>lk[N]; void modify(int i,int x) { i+=d;mn[i]=x; while(i>>=1)mn[i]=min(mn[i*2],mn[i*2+1])+ad[i]; } void suf_add(int i,int w) { if(i>n)return ; i+=d;mn[i]+=w;ad[i]+=w; while(i>1) { if(i%2==0){mn[i+1]+=w;ad[i+1]+=w;} i>>=1; mn[i]=min(mn[i*2],mn[i*2+1])+ad[i]; } } int s0,s1,st[N]; void dfs(int i,int s) { if(mn[i]+s>=0)return ; if(i>d) { //cerr<<i-d<<" "<<mn[i]+s<<endl; st[++s1]=ndy[i-d]; return ; } rep(j,0,1)dfs(i*2+j,s+ad[i]); } int main() { #ifdef kcz freopen("1.in","r",stdin);//freopen("1.out","w",stdout); #endif n=read(); rep(i,1,n){a[i]=read();b[i]=read();} rep(i,1,n)q[i]=b[i]; sort(q+1,q+n+1); rep(i,1,n) { dy[i]=lower_bound(q+1,q+n+1,b[i])-q; dy1[i]=lower_bound(q+1,q+n+1,b[i]+1)-q; dy[i]+=h[dy[i]]++; ndy[dy[i]]=i; } for(d=1;d<n;d<<=1);d-=1; rep(i,1,n)modify(dy[i],-(n-1+a[i]-1)/a[i]); rep(i,1,n) { suf_add(dy1[i],1); for(int j=1;j<n;j+=a[i])lk[j].push_back(i); } rep(i,n+1,d+1)modify(i,1e9); //cerr<<mn[d+1]<<endl; while(mn[1]<0) { ++s0; int s1_0=s1; dfs(1,0); rep(i,s1_0+1,s1) { int x=st[i]; //cerr<<x<<endl; ans[x]=s0; modify(dy[x],1e9); suf_add(dy1[x],-1); for(auto y:lk[n-i]) if(!ans[y])modify(dy[y],mn[dy[y]+d]+1); } } rep(i,1,n)printf("%d ",ans[i]); }