生活随笔
收集整理的這篇文章主要介紹了
51Nod 1530 稳定方块
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
瓦西亞和皮臺亞擺放了m個方塊。方塊被編號為0到m-1(每個號碼出現恰好一次)。現在建立一個座標系OX表示地面,OY的方向是豎直向上的。每一方塊的左下角有一個座標而且是整點座標。
擺放好的方塊一定要是穩定的。穩定的含意是每一個不在地面上的方塊在他的下面至少有一個方塊與他相接觸。可以是共邊,也可以是共點的。也就是說如果方塊座標為(x,y),要么y=0,或者存在一個方塊的座標為(x-1,y-1)或者 (x,y-1) 或者 (x+1,y-1)。
現在瓦西亞和皮臺亞要輪流把這些方塊一個個拆下來。按照拆下來的順序從左到右擺成一行,那么方塊上面的編號就會組成一個m進制的數字。
拆的過程中,要始終保持剩下的方塊穩定。瓦西亞想要最終的數字盡可能大,而皮臺亞想要盡可能小,瓦西亞先開始拆。
請幫助計算一下最終形成的數字是多少,結果比較大,輸出對 109+9 取余后的結果。
解題報告:
用時:1h10min,1WA1TLE
一開始認為就是開優先隊列跑拓撲排序,后來發現度不為0也可以入隊,所以只拿了60,然后我想到了正確貪心:
對于瓦西亞的從后往前枚舉,直到出現第一個能消除的,皮臺亞的同理.
然后打了這個貪心的暴力驗證一下,發現是對的,考慮優化:
我們把所有可以消除的點丟入優先隊列中,然后每次取出編號最小的,我們需要維護一個\(res[i]\),表示\(i\)最下面還有幾個沒有消除的點,然后我們檢查一個點不合法我們就判斷其上面的點是否\(res[i]<=1\),注意每消除一個點就要去更新上面點的\(res\)值,并且如果\(res[i]<=1\)時還要check他上方的點的下方的三個點是否會不合法,這樣一個點最多入隊三次,均攤復雜度\(O(nlogn)\)
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <cstdio>
#include <vector>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=1e5+5,inf=1e9+5,mod=1e9+9;
int n;bool vis[N];
struct node{int x,y,id;bool operator <(const node &pp)const{if(y!=pp.y)return y<pp.y;return x<pp.x;}
}a[N];
struct comp{bool operator ()(int &i,int &j)const{return i>j;}
};
priority_queue<int>q;
priority_queue<int,vector<int>,comp>qm;
vector<int>s[N];
int b[N],m=0,num=0,head[N],to[N*3],nxt[N*3],du[N],re[N];
void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
bool check(int x){if(vis[x])return false;for(int i=head[x];i;i=nxt[i]){if(!vis[to[i]] && du[to[i]]<=1)return false;}return true;
}
bool ca[N];
void solve(){bool t=0;int x;for(int i=1;i<=n;i++){if(!t){while(!q.empty()){if(!ca[q.top()])q.pop();else break;}x=q.top();q.pop();}else{while(!qm.empty()){if(!ca[qm.top()])qm.pop();else break;}x=qm.top();qm.pop();}vis[x]=true;ca[x]=false;for(int k=0,sz=s[x].size(),u;k<sz;k++){u=s[x][k];if(check(u))ca[u]=true,qm.push(u);q.push(u);}for(int j=head[x];j;j=nxt[j]){du[to[j]]--;for(int k=0,sz=s[to[j]].size(),u;k<sz;k++){u=s[to[j]][k];if(!check(u))ca[u]=false;else{ca[u]=true;qm.push(u);q.push(u);}}}re[i]=x-1;t^=1;}ll ans=0,mul=1;for(int i=n;i>=1;i--){ans+=mul*re[i];ans%=mod;mul*=n;mul%=mod;}printf("%lld\n",ans);
}
void work()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d",&a[i].x,&a[i].y);a[i].id=i;}sort(a+1,a+n+1);for(int i=1;i<=n;i++)b[++m]=a[i].y;int sta;for(int i=1;i<=n;i++){sta=lower_bound(b+1,b+m+1,a[i].y-1)-b;for(int j=sta;j<i;j++){if(a[j].y!=a[i].y-1)break;if(abs(a[j].x-a[i].x)<=1){link(a[j].id,a[i].id);du[a[i].id]++;s[a[i].id].push_back(a[j].id);}}}for(int i=1;i<=n;i++){if(check(i))q.push(i),qm.push(i),ca[i]=true;}solve();
}int main()
{work();return 0;
}
轉載于:https://www.cnblogs.com/Yuzao/p/7524081.html
總結
以上是生活随笔為你收集整理的51Nod 1530 稳定方块的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。