[九省聯考2018]IIIDX
阿新 • • 發佈:2019-03-11
所有 typedef print 1+n fir scanf .org 答案 etc
然後每次更新後需要在修改位置的右邊全部減去子樹大小。註意,每次遍歷完一個父親的時候要加上他的子樹大小。相當於把原來預留的空間放了出來。
然後就完事了……代碼不長……
傳送門
形式化題意:一棵樹,對於每個節點賦予一個給定的權值,使得每個節點都不大於子樹內節點,同時滿足編號小的點盡可能大。
首先在所有給定的數不同的時候只要貪心一次,從小到大把數排序,之後建樹在上面跑dfs,按dfn從小到大給權值。
但是這樣在有相同的數據的時候是會錯的。因為有可能通過交換使得子樹內節點權值和根相等。(例子在luogu討論區有的)
我們重新考慮一下。把所有的數從大到小排序,記錄\(C_i\)為每個點左邊還能被使用的權值個數。這樣的話每次找一個位置賦權值的話,其實就是找一個位置使得它右邊所有位置的\(C_i\)不大於子樹大小。這個可以在線段樹上二分。
不過二分出來的不一定是最好的答案,因為有重復的數字所以你取最優的結果一定是在最右側,需要額外維護一下應該調到的位置。
然後就完事了……代碼不長……
#include<bits/stdc++.h> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') #define pr pair<int,int> #define mp make_pair #define fi first #define sc second using namespace std; typedef long long ll; const int M = 1000005; const int N = 10000005; int read() { int ans = 0,op = 1;char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();} while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar(); return ans * op; } struct tree { int minn,lazy; }t[M<<2]; bool cmp(int x,int y){return x > y;} int n,a[M],b[M],cur = 1,dfn[M],idx,fa[M],size[M],ans[M],cnt[M]; double k; void pushdown(int p) { t[p<<1].lazy += t[p].lazy,t[p<<1|1].lazy += t[p].lazy; t[p<<1].minn += t[p].lazy,t[p<<1|1].minn += t[p].lazy; t[p].lazy = 0; } void build(int p,int l,int r) { if(l == r) {t[p].minn = l;return;} int mid = (l+r) >> 1; build(p<<1,l,mid),build(p<<1|1,mid+1,r); t[p].minn = min(t[p<<1].minn,t[p<<1|1].minn); } int query(int p,int l,int r,int k) { if(l == r){return t[p].minn >= k ? l : l + 1;} pushdown(p); int mid = (l+r) >> 1; if(k <= t[p<<1|1].minn) return query(p<<1,l,mid,k); else return query(p<<1|1,mid+1,r,k); } void update(int p,int l,int r,int kl,int kr,int val) { if(l == kl && r == kr) {t[p].minn += val,t[p].lazy += val;return;} pushdown(p); int mid = (l+r) >> 1; if(kr <= mid) update(p<<1,l,mid,kl,kr,val); else if(kl > mid) update(p<<1|1,mid+1,r,kl,kr,val); else update(p<<1,l,mid,kl,mid,val),update(p<<1|1,mid+1,r,mid+1,kr,val); t[p].minn = min(t[p<<1].minn,t[p<<1|1].minn); } int main() { n = read(),scanf("%lf",&k); rep(i,1,n) a[i] = read(); sort(a+1,a+1+n,cmp); per(i,n-1,1) cnt[i] = (a[i] == a[i+1]) ? cnt[i+1] + 1 : 0; rep(i,1,n) fa[i] = (int)floor(i/k),size[i] = 1; per(i,n,1) size[fa[i]] += size[i]; build(1,1,n); rep(i,1,n) { if(fa[i] && fa[i] != fa[i-1]) update(1,1,n,ans[fa[i]],n,size[fa[i]]-1); int cur = query(1,1,n,size[i]); cur += cnt[cur],cnt[cur]++,ans[i] = cur; update(1,1,n,cur,n,-size[i]); } rep(i,1,n) printf("%d ",a[ans[i]]);enter; return 0; }
[九省聯考2018]IIIDX