CodeForces 520D Cubes

题意:

二维平面内有一个图形由n(10^5)个标有0~n-1的方块组成 保证它是稳定的 即每个方块要么落在地面上 要么下面(边或点相交)有至少一个方块支撑 现在两个人轮流拆这个图形 要求拆的过程中图形仍稳定 拆下的方块上的数字会形成一个n进制的数 先手想让这个数最大 后手想最小 问最后这个数字是几

思路:

简单的贪心思路 在不毁坏稳定性的前提下 先手拿大数字 后手拿小数字 程序写的暴力会n^2造成TLE

那么我们维护一个有序队列(set维护) 这里面装着可以拆的数字 每次从里面拿走想要的数字

注意的是进入set的数字在拆之前仍要检查可行性! 因为最开始可能是_-_这种形状 那么这3个都进入set 假设拆掉了右边 即变成了_-这样 那么这时左边就不能拆了 即使它在set里

每次拆完一个数字 检查它下面的3个位置 这三个位置也许具有拆掉的可能了

PS:

使用STL要小心点 一边遍历一遍删除元素是很危险的!!!

代码:

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<map>#include<set>#include<vector>#include<queue>#include<cstdlib>#include<ctime>#include<cmath>using namespace std;typedef long long LL;#define N 100010#define mod 1000000009#define mp(x,y) (make_pair(x,y))int n;int x[N],y[N];map<pair<int,int>,int> f;set<int> g;LL ans;bool yes(int tmp){int X,Y;X=x[tmp]+1;Y=y[tmp]+1;if(f.count(mp(X,Y))){if(!f.count(mp(X,Y-1))&&!f.count(mp(X+1,Y-1))){return false;}}X=x[tmp];Y=y[tmp]+1;if(f.count(mp(X,Y))){if(!f.count(mp(X-1,Y-1))&&!f.count(mp(X+1,Y-1))){return false;}}X=x[tmp]-1;Y=y[tmp]+1;if(f.count(mp(X,Y))){if(!f.count(mp(X-1,Y-1))&&!f.count(mp(X,Y-1))){return false;}}return true;}void add(int tmp){int X,Y;X=x[tmp]-1;Y=y[tmp]-1;if(f.count(mp(X,Y))){int u=f[mp(X,Y)];if(yes(u)) g.insert(u);}X=x[tmp];Y=y[tmp]-1;if(f.count(mp(X,Y))){int u=f[mp(X,Y)];if(yes(u)) g.insert(u);}X=x[tmp]+1;Y=y[tmp]-1;if(f.count(mp(X,Y))){int u=f[mp(X,Y)];if(yes(u)) g.insert(u);}}int main(){scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&x[i]);scanf("%d",&y[i]);f[mp(x[i],y[i])]=i;}for(int i=0;i<n;i++){if(yes(i)) g.insert(i);}for(int i=0;i<n;i++){if(i&1){while(!g.empty()){int tmp=(*g.begin());if(yes(tmp)){ans=((ans*n%mod)+tmp)%mod;g.erase(tmp);f.erase(mp(x[tmp],y[tmp]));add(tmp);break;}g.erase(tmp);}}else{while(!g.empty()){int tmp=(*g.rbegin());if(yes(tmp)){ans=((ans*n%mod)+tmp)%mod;g.erase(tmp);f.erase(mp(x[tmp],y[tmp]));add(tmp);break;}g.erase(tmp);}}}printf("%I64d\n",ans);return 0;}

,与其在那里苦苦挣扎,碍于面子硬撑,倒不如微笑着面对,

CodeForces 520D Cubes

相关文章:

你感兴趣的文章:

标签云: