CF378 D. Preparing for the Contest
阿新 • • 發佈:2021-07-01
題目傳送門:https://codeforces.com/problemset/problem/378/D
題目大意:
有 \(n\) 個人,\(m\) 個bug,已經總資金\(s\)
第\(i\)個bug的難度為\(a_i\),第\(i\)個人的能力值為\(b_i\),其需要的工資為\(c_i\)
支付工資\(c_i\)後,第\(i\)個人就可以每天處理一個難度不超過\(b_i\)的bug,持續時間無限
問能否選出一些人處理這些bug?如果能,輸出所需的最少天數\(d\),以及每個bug是由誰處理的
考慮二分天數,如果需要花費\(d\)天解決問題,我們就儘可能讓所有人都工作\(d\)天,至少能力越強的人,越應當工作\(d\)
故判斷天數\(d\)是否可行時,我們在剩餘的bug中找到最難的一個\(k\),選取能力值\(b_i\geqslant a_k\)中\(c_i\)最小的一個,然後除去\(d\)個bug,以此類推直到bug處理完畢
將能力值作為下標,轉化為線段樹維護
注:同一能力值的人有多個
/*program from Wolfycz*/ #include<map> #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define Fi first #define Se second #define ll_inf 1e18 #define MK make_pair #define sqr(x) ((x)*(x)) #define pii pair<int,int> #define int_inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline char gc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } template<typename T>inline T frd(T x){ int f=1; char ch=gc(); for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } template<typename T>inline T read(T x){ int f=1; char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline void print(int x){ if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } const int N=1e5; int B[N+10],C[N+10],list[(N<<1)+10],All,T; vector<int>pos[(N<<1)+10],_tmp[(N<<1)+10]; struct S1{ #define ls (p<<1) #define rs (p<<1|1) int Tree[(N<<3)+10],Temp[(N<<3)+10]; void copy(){ memcpy(Temp,Tree,sizeof(Tree)); for (int i=1;i<=T;i++) _tmp[i]=pos[i]; } void paste(){ memcpy(Tree,Temp,sizeof(Temp)); for (int i=1;i<=T;i++) pos[i]=_tmp[i]; } void update(int p){Tree[p]=C[Tree[ls]]<C[Tree[rs]]?Tree[ls]:Tree[rs];} void update(int &x,int y){x=C[x]<C[y]?x:y;} void Build(int p,int l,int r){ if (l==r){ Tree[p]=pos[l].empty()?0:pos[l].front(); return; } int mid=(l+r)>>1; Build(ls,l,mid); Build(rs,mid+1,r); update(p); } void Modify(int p,int l,int r,int x){ if (l==r){ pos[l].erase(pos[l].begin()); Tree[p]=pos[l].empty()?0:pos[l].front(); return; } int mid=(l+r)>>1; if (x<=mid) Modify(ls,l,mid,x); if (x>mid) Modify(rs,mid+1,r,x); update(p); } int Query(int p,int l,int r,int L,int R){ if (L<=l&&r<=R) return Tree[p]; int mid=(l+r)>>1,Ans=0; if (L<=mid) update(Ans,Query(ls,l,mid,L,R)); if (R>mid) update(Ans,Query(rs,mid+1,r,L,R)); return Ans; } void print(int p,int l,int r){ if (l==r) return; int mid=(l+r)>>1; print(ls,l,mid); print(rs,mid+1,r); } #undef ls #undef rs }ST;//Segment Tree struct node{ int Val,ID; node(int _Val=0,int _ID=0){Val=_Val,ID=_ID;} bool operator <(const node &tis)const{return Val<tis.Val;} void operator =(int x){Val=x;} }A[N+10]; bool check(int x,int m){ ST.paste(); ll use=0; for (int i=1;i<=m;i+=x){ int pos=ST.Query(1,1,T,A[i].Val,T); use+=C[pos]; if (use>All) return 0; ST.Modify(1,1,T,B[pos]); } return use<=All; } int Ans[N+10]; void solve(int x,int m){ ST.paste(); for (int i=1;i<=m;i+=x){ int pos=ST.Query(1,1,T,A[i].Val,T); Ans[A[i].ID]=pos; ST.Modify(1,1,T,B[pos]); } for (int i=1;i<=m;i++) if (!Ans[A[i].ID]) Ans[A[i].ID]=Ans[A[i-1].ID]; printf("YES\n"); for (int i=1;i<=m;i++) printf("%d%c",Ans[i],i==m?'\n':' '); } bool cmp(int x,int y){return C[x]<C[y];} int main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); int n=read(0),m=read(0),tot=0; All=read(0); C[0]=int_inf; for (int i=1;i<=m;i++) A[i]=list[++tot]=read(0); for (int i=1;i<=n;i++) B[i]=list[++tot]=read(0); for (int i=1;i<=n;i++) C[i]=read(0); sort(list+1,list+1+tot); T=unique(list+1,list+1+tot)-list-1; for (int i=1;i<=m;i++) A[i]=lower_bound(list+1,list+1+T,A[i].Val)-list; for (int i=1;i<=n;i++) B[i]=lower_bound(list+1,list+1+T,B[i] )-list; for (int i=1;i<=m;i++) A[i].ID=i; sort(A+1,A+1+m); reverse(A+1,A+1+m); for (int i=1;i<=n;i++) pos[B[i]].push_back(i); for (int i=1;i<=T;i++) sort(pos[i].begin(),pos[i].end(),cmp); ST.Build(1,1,T); ST.copy(); int l=1,r=m; while (l<=r){ int mid=(l+r)>>1; if (check(mid,m)) r=mid-1; else l=mid+1; } if (r==m){ printf("NO\n"); return 0; } solve(r+1,m); return 0; }