2020華中師範大學新生賽H--七日狂想曲
阿新 • • 發佈:2020-12-28
題面
這題我一看,最小費用流直接往上打,很快呀,然後無情TLE,十分正常,畢竟最小費用流複雜度\(O(nm^2)\),然後就看到了神仙題解思維,延遲貪心。
我首先打的最小費用流,是因為我發現了每個地方的每個藥材去的地方不一樣,那麼就需要知道每個藥材最合適的去處,那麼最小費用流就可以模擬這個過程,但是複雜度不夠。
然後是題解的思路
首先觀察資料範圍,可以看出最多\(O(n^2*log(n))\),這裡開始構思演算法。
對於某一個位置,我們需要對於其中每一個進出的藥材進行路徑選擇,對於,每個拿出的藥材,要麼先拿出去,則當前這個藥材轉移的價值 \(val=b*(n-i+1)\),或者轉移到一個固定的位置,那麼為了確定這個位置,列舉是不可能的,過不去的,但又有可能有這種情況,所以我們這裡先暫時滿足於\(val\)
綜上,
1:對於每一個需要轉出的點,列舉當前的變化數目,然後\(val_i=min(b*(n-i+1,c*(i-j)-val_j)\),j是以前的已經得到應有數量的點,但\(c*(i-j)-val_j\)可以進行更少的操作次數,故這裡可以更新.
2:同理,對於每個要獲得的點\(val_j=min(a*i,c*(i-j)-val_j)\),
對於\(min()\)
總結:這道題其實也算是到貪心,但很難想到,人還是太菜了
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<map> #include<bitset> #include<queue> #include<queue> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #define rpe(i,a,b) for(int i=a;i>=b;--i) #define pts putchar('\n') #define ptc putchar(' ') typedef long long ll; typedef unsigned long long ull; const ll inf=1e18;; const int maxn=1e3+9; const int maxm=2e6+2; const int mod=998244353; const int base=131; namespace IO{ ll read(){ ll a=1,b=0;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')a=-1;c=getchar();} while(c>='0'&&c<='9'){b=(b<<3)+(b<<1)+c-'0';c=getchar();} return a*b ; } void print (ll x){ if(x<0) putchar('-'),x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } } using namespace IO; ll n; ll a,b,c; ll u[maxn],v[maxn]; priority_queue<ll , vector<ll> , greater<ll> >q1,q2; ll ans=0; int main(){ //freopen("3.IN","r",stdin); n=read(),a=read(),b=read(),c=read(); rep(i,1,n) u[i]=read(); rep(i,1,n) v[i]=read(); ll val; rep(i,1,n){ rep(j,1,u[i]-v[i]){//向外轉 val=1LL*b*(n-i+1); if(!q2.empty()){ val=min(val,q2.top()+1LL*c*i); q2.pop(); } ans+=val; q1.push(-val-1LL*c*i); } rep(j,1,v[i]-u[i]){ val=1LL*a*i; if(!q1.empty()){ val=min(val,q1.top()+1LL*c*i); q1.pop(); } ans+=val; q2.push(-val-1LL*c*i); } } print(ans); return 0; }