B-Bessie and MEX
思路:順,逆填都可以.見程式碼註釋
void solve(){ //補B--不用str.find來維護,這個是o(n)的。用set的count() or find()來維護,這兩個都是o(logn)的
int n;cin>>n;
// // 順著填:填的數字=MEX.find('0')-ai or 填了MEX[MEX.find('0')]='1',之後MEX.find('0')-剛才填的位置--這樣雖然是對的,但是實現容易超時
// //順著填:x>=0,那麼pi即為當前mex;如果x<0,那麼pi=mex-x;
// // 因為x>=0,即NewMex-CurMex>=0,那麼mex一定是增加的,那pi只能填當前mex;
// // 如果x<0,那麼NewMex不能增加,那隻能保持不變,那pi只能是mex-x;
set<int> st;
int mex=0;
for(int i=1;i<=n;i++){
int x; cin>>x;
while(st.find(mex)!=st.end()) mex++;
if(x>=0){
cout<<mex<<" ";
st.insert(mex);
}
else{
cout<<mex-x<<" ";
st.insert(mex-x);
}
}
cout<<endl;
}
void solve(){ //補B
//倒著填:因為填了最後一個之後,mex必然為n,那麼最後一個pi就是n-arr[n];那麼填n-1個時,因為只有pn還沒出現過,那麼此時mex為pn
//但是遇到負數時填的數字會更大,mex不會改變,那麼只有當mex-ai更小才更新mex
//我們知道最後一個位置的MEX是n,那麼n−pn=an,我們可以得出 pn=n−an
//現在知道了pn,那麼可以確定前n-1個數字的MEX.跟求出pn是一樣的.一直這樣計算下去即可.
int n; cin>>n;
int arr[200005];
for(int i=1;i<=n;i++) cin>>arr[i];
int cur=n-arr[n];
stack<int> stk;
stk.emplace(cur);
for(int i=n-1;i>=1;i--){
stk.emplace(cur-arr[i]);
cur=min(cur,cur-arr[i]);
}
while(stk.size()){
cout<<stk.top()<<" ";
stk.pop();
}
cout<<endl;
}
C1-Bessie's Birthday Cake (Easy Version)
思路:見程式碼註釋.
void solve(){ //補C1 新
int n,x,y; cin>>n>>x>>y;
int ans=x-2; //!!顯然!!任意x個點內部可以構成x-2個三角形.對於外部點三角形,也是顯然,只有兩個點距離恰好為2點時候可以構成外部一個三角形
int arr[200005];
for(int i=1;i<=x;i++) cin>>arr[i];
sort(arr+1,arr+x+1);
for(int i=2;i<=x;i++){
if(arr[i]-arr[i-1]==2) ans++;
}
if(arr[1]+n-arr[x]==2) ans++; //特判一下環的最後一個和第一個
cout<<ans<<endl;
}
C2-Bessie's Birthday Cake (Hard Version)
思路:見程式碼註釋
void solve(){ //補C2 !貪心! 重重貪心,先是貪偶數,再是貪從小的先拿
int n,x,y; cin>>n>>x>>y;
int ans=x-2;
int arr[200005];
for(int i=1;i<=x;i++) cin>>arr[i];
sort(arr+1,arr+x+1);
arr[x+1]=arr[1]+n;
//priority_queue<int> pq; //不能單調從大到小排。因為偶的是比奇的更有價值的,所以應該優先考慮偶的區間,還有y剩餘的話,再考慮奇的區間(貪心)
priority_queue<int,vector<int>,greater<int>> pqodd,pqeven; //小根堆,優先拿小的
for(int i=1;i<=x;i++){
if(arr[i+1]-arr[i]==2) ans++;
if(arr[i+1]-arr[i]>2&&(arr[i+1]-arr[i])%2==0) pqeven.emplace(arr[i+1]-arr[i]);
if(arr[i+1]-arr[i]>2&&(arr[i+1]-arr[i])%2!=0) pqodd.emplace(arr[i+1]-arr[i]);
}
while(pqeven.size()&&y){
//先貪心地跑偶的,因為得到相同的三角形個數,偶的可以花費更少y.
// 先拿小的,是因為小的更值當;如果先拿大的,可能因為y不夠,導致貪心沒有貪到
int cur=pqeven.top();
pqeven.pop();
if(cur%2==0&&y>=cur/2-1){
y-=cur/2-1,ans+=cur/2-1,ans+=cur/2;
}
else if(cur%2==0&&y<cur/2-1){
ans+=y,ans+=y,y=0;
}
else if(cur%2!=0&&y>=cur/2){
y-=cur/2,ans+=cur/2,ans+=cur/2;
}
else if(cur%2!=0&&y<cur/2){
ans+=y,ans+=y,y=0;
}
}
while(pqodd.size()&&y){
int cur=pqodd.top();
pqodd.pop();
if(cur%2==0&&y>=cur/2-1){
y-=cur/2-1,ans+=cur/2-1,ans+=cur/2;
}
else if(cur%2==0&&y<cur/2-1){
ans+=y,ans+=y,y=0;
}
else if(cur%2!=0&&y>=cur/2){
y-=cur/2,ans+=cur/2,ans+=cur/2;
}
else if(cur%2!=0&&y<cur/2){
ans+=y,ans+=y,y=0;
}
}
cout<<ans<<endl;
}
總結:這場只寫出來AB題,B題因為用str.find()來維護,被hack了。所以只有A題,一場扣了100多分..再接再厲吧。