1. 程式人生 > >5249: [2018多省省隊聯測]IIIDX

5249: [2018多省省隊聯測]IIIDX

date namespace tag tps https target min bzoj ace

5249: [2018多省省隊聯測]IIIDX

鏈接

分析:

  貪心。

  將給定的權值從大到小排序,從第一個往後挨個賦值,考慮第i個位置可以賦值那些樹。首先滿足前面必須至少有siz[i]個權值沒選,如果存在相同的數,盡量往後選。

  那麽可以給每個權值記錄一個值F[i],表示i左邊可以選多少個權值了。還要和後面的取一個最小值才是真正的能選多少個。

  在線段樹上分治找到這個位置。

  註意在bzoj上,fa[i]=int(1.0*i/k) 有精度誤差,而寫成floor就可以了。

代碼:

#include<cstdio>
#include<algorithm>
#include
<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; typedef long long LL; inline
int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f; } const int N = 500005; int Mn[N << 2], tag[N << 2], R[N], fa[N], siz[N], ans[N], cnt[N], w[N]; inline bool cmp(int x,int y) { return
x > y; } inline void pushup(int rt) { Mn[rt] = min(Mn[rt << 1], Mn[rt << 1 | 1]); } inline void pushdown(int rt) { tag[rt << 1] += tag[rt];tag[rt << 1 | 1] += tag[rt]; Mn[rt << 1] += tag[rt];Mn[rt << 1 | 1] += tag[rt]; tag[rt] = 0; } void build(int l,int r,int rt) { tag[rt] = 0; if (l == r) { Mn[rt] = l; return ; } int mid = (l + r) >> 1; build(lson); build(rson); pushup(rt); } void update(int l,int r,int rt,int L,int R,int v) { if (L <= l && r <= R) { tag[rt] += v; Mn[rt] += v; return ; } if (tag[rt]) pushdown(rt); int mid = (l + r) >> 1; if (L <= mid) update(lson, L, R, v); if (R > mid) update(rson, L, R, v); pushup(rt); } int query(int l,int r,int rt,int x) { if (l == r) return l + (Mn[rt] < x); if (tag[rt]) pushdown(rt); int mid = (l + r) >> 1; if (x <= Mn[rt << 1 | 1]) return query(lson, x); else return query(rson, x); } int main() { int n = read(); double k; scanf("%lf", &k); for (int i = n; i >= 1; --i) fa[i] = floor(1.0 * i / k), siz[i] ++, siz[fa[i]] += siz[i]; for (int i = 1; i <= n; ++i) w[i] = read(); sort(w + 1, w + n + 1, cmp); build(1, n, 1); for (int i = n; i >= 1; --i) { if (w[i] == w[i + 1]) R[i] = R[i + 1]; else R[i] = i; } for (int i = 1; i <= n; ++i) { if (fa[i] && fa[i] != fa[i - 1]) update(1, n, 1, ans[fa[i]], n, siz[fa[i]] - 1); int x = query(1, n, 1, siz[i]); x = R[x]; x -= cnt[x]; cnt[x] ++; ans[i] = x; update(1, n, 1, x, n, -siz[i]); } for (int i = 1; i <= n; ++i) printf("%d ", w[ans[i]]); return 0; }

5249: [2018多省省隊聯測]IIIDX