题解:P12148 【MX-X11-T2】「蓬莱人形 Round 1」所以我放弃了音乐
fish_love_cat · · 题解
赛时想抢首杀,第一个开的就是这题。
然后爆炸了,先去写了其他题转回来才发现自己糖成啥了。
最左端显然必须消耗操作,然后就是从下往上遍历会劣于从上往下遍历。
因为当前列最下面的点能消的较低点上面一定消不掉,但如果从它开始,它会锁定到上面可能能消的点,那这样上面的贡献就被挤掉了。
于是你像我一样对每一列写了个可删堆模拟每次操作发现挂了。
考虑这么一张图:
...@
.@@.
.@..
@.@.
@ 表示棋子,. 表示空地。
我们的做法:
...1
.21.
.1..
1.3.
答案为
正解:
...1
.11.
.2..
2.2.
答案为
这启示我们对于每一个棋子进行转移而不是直接模拟。
从左到右从上到下的枚举棋子,然后从能抵达它并且未使用的棋子中取最上面的点进行转移。
无法转移的计入答案。
然后你会发现做完了,时间复杂度综合
#include<bits/stdc++.h>
#define int long long
using namespace std;
vector<int>ve[1000005];
map<int,bool>mp[1000005];
bool cmp(int a,int b){
return a>b;
}
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
int u,v;
cin>>u>>v;
mp[u][v]=1;
ve[u].push_back(v);
}
int ans=0;
for(int i=1;i<=1000000;i++){
if(ve[i].size()==0)continue;
sort(ve[i].begin(),ve[i].end(),cmp);
for(int j=0;j<ve[i].size();j++){
if(mp[i-1][ve[i][j]+1])mp[i-1][ve[i][j]+1]=0;
else if(mp[i-1][ve[i][j]])mp[i-1][ve[i][j]]=0;
else if(mp[i-1][ve[i][j]-1])mp[i-1][ve[i][j]-1]=0;
else ans++;
}
}
cout<<ans;
return 0;
}