10.13多校聯訓
阿新 • • 發佈:2021-10-13
題意略。
T1 AT2672 [AGC018C] Coins
Sol
考場上面想的是六遍貪心做法,可惜寫了300行使用替換功能的時候C++死了,心態爆炸就沒再寫。事後證明演算法是正確的,但是碼量上並不優秀。
這是我當時考試的解法:首先有個顯然的貪心:每個人儘可能去取他有的最多的幣種。但是會出現有的幣種大家都多,而有的又缺的情況,所以需要調配多人的幣種。接下來還可以證明的是對於三個幣種的調配,一定是無環的,即如果有人從金幣調到了銀幣,那就不會有銀幣調到金幣,因為這樣就不如他們都不調;三個的環同理。因此處於調配圖的頂端的幣種是不受其他幣種的影響的,直接貪心,然後順次貪心即可。但是無法確定順序,所以列舉所有的六種貪心順序取最值即可。由於碼量巨大,所以其實並不可取。
題解的優質解法是這樣的:假設每個人都取金幣,然後題目就變成了從\(n\)
Code
#include<bits/stdc++.h> using namespace std; #define int long long inline int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();} while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar(); return f?x:-x; } const int maxn=100010; int n,R,Y,G,ans,mx=-1e18; priority_queue<int,vector<int>,greater<int> >qu1,qu2; int maxb[maxn],maxa[maxn]; struct node { int a,b; bool operator<(const node &x)const { return a-b>x.a-x.b; } }; node dl[maxn]; signed main() { // freopen("collection.in","r",stdin); // freopen("collection.out","w",stdout); R=read();Y=read();G=read(); n=R+Y+G; for(int i=1;i<=n;i++) { int x=read(),y=read(),z=read(); ans+=x; y-=x;z-=x; dl[i]=(node){y,z}; } sort(dl+1,dl+n+1); if(Y) { for(int i=1;i<=Y;i++) { qu1.push(dl[i].a); maxb[i]=maxb[i-1]+dl[i].a; } for(int i=Y+1;i<=n;i++) { if(qu1.top()<dl[i].a) { maxb[i]=maxb[i-1]-qu1.top()+dl[i].a; qu1.pop();qu1.push(dl[i].a); }else maxb[i]=maxb[i-1]; } } if(G) { for(int i=1;i<=G;i++) { qu2.push(dl[n-i+1].b); maxa[n-i+1]=maxa[n-i+2]+dl[n-i+1].b; } for(int i=G+1;i<=n;i++) { if(qu2.top()<dl[n-i+1].b) { maxa[n-i+1]=maxa[n-i+2]-qu2.top()+dl[n-i+1].b; qu2.pop();qu2.push(dl[n-i+1].b); }else maxa[n-i+1]=maxa[n-i+2]; } } for(int i=Y;i<=n-G;i++)mx=max(mx,maxb[i]+maxa[i+1]); printf("%lld\n",ans+mx); return 0; }
T2 AGC記不得了
Sol
真的不會。考場上因為有70的部分分都是修改操作很少的,所以直接合並相同操作的區間然後暴力。正解是按照從低位到高位建一顆\(0,1,2trie\)樹,對於每次的0操作可以直接換子節點,1操作由於是從低到高修改,所以每次修改的複雜度不超過\(O(n)\)。
Code
無。
T3 CF960H Santa's Gift
Sol
把柿子化一下就完了,樹剖線段樹維護修改即可(亂寫的)。
Code
更莫得。
T4 CF????
總之就3500的題,爬了。