51Nod 1482 部落訊號(單調棧)

2021-08-21 10:48:57 字數 1816 閱讀 7790

乙個長度為

n n

的環 a' role="presentation" style="position: relative;">a

a,如果環上有一對數 x,

y x,y

,當連線 x,

y x,y

的兩對弧中任意一對上不存在比 mi

n min

大的數,則稱 x,

y x,y

可以互相看見,問有多少對數可以互相看見。 3≤

n≤106

3 ≤n

≤10

6首先,與環有關的問題,最基本的思路就是段環成鏈。因為連線 x,

y x,y

的圓弧,一定不必穿過環上的最大值,所以可以去掉環上最大值並把環拆成鏈,最後重新算一遍最高點的貢獻即可。不難發現,將

x x

作為較低點,它能鏈結的點有左邊第乙個比它大的點和右邊第乙個比它大的點,於是想到單調棧。但是這樣有乙個問題,如果單調棧中出現了相同元素,那麼點

x' role="presentation" style="position: relative;">x

x還能連線到所有與

x x

大小相同的點。所以還要特殊處理這一類點。單調棧進行的過程中始終保持序列的遞減,那只用用

x' role="presentation" style="position: relative;">x

x替換棧內元素時,維護乙個

s s

陣列如果遇到相同元素,則通過累加得到與

x' role="presentation" style="position: relative;">x

x相同的元素個數即可。準確的說,是

x x

向左邊拓展,在遇到比它大的點時停下,中途遇到與

x' role="presentation" style="position: relative;">x

x相等的元素的個數(當然,除了將所有數的

s s

值加起來,也可以加上所有的 ck

2' role="presentation" style="position: relative;">c2k

ck2,其中

k k

為乙個滿足上述要求,值相等的點集中點的個數)。

由於這題有些卡語言,所以用

c' role="presentation" style="position: relative;">c

c語言交了

#include#define for(i,x,y) for(register int i=(x);i<=(y);++i)

#define dor(i,x,y) for(register int i=(x);i>=(y);--i)

#define n 1000003

typedef long long ll;

int mark[n];

int a[n],t[n],s[n],n;

int stk[n],top;

int p,mx=-1,h;

ll ans;

int main()

if(top)ans++;

stk[++top]=i;

}a[n+1]=2e9,stk[top=0]=n+1;

dor(i,n,1)

for(i,1,n)ans+=s[i];

h=-1;

for(i,1,n)}}

h=-1;

dor(i,n,1)}}

printf("%lld\n",ans);

return 0;

}

51Nod1482 部落訊號

題意 有n個部落圍成一圈,每個部落都有乙個高度,如果兩個部落之間的部落高度都低於這兩個部落的高度,那麼這兩個部落則互相可見,乙個部落從順時針或逆時針方向看到另乙個部落都算互相可見 題解 單調棧 乙個部落從順時針方向看到與它互相可見的部落,一定是一段連續遞增的序列,逆時針同理 這就很像單調棧的維護方式...

2150 部落戰爭

題目鏈結 題目大意 給出一張地圖,乙個軍隊要征戰整個土地。一塊土地只能經過一次,有x的地方不能走,軍隊只會走r c個格仔,只會向下走,問最少需要多少軍隊能夠征戰所有的土地 題解 比較 的dag最小路徑覆蓋,把可行點連邊,搞成二分圖就好了 我的收穫 水啊 include include include...

41 部落人乘法

41 部落人乘法 問題描述 明明熱愛數學,他的爸爸也有意培養明明對數學的興趣。一次,為了拓展明明的知識面,爸爸給明明講了乙個原始部落人計算乘法的方法 據說原始部落人以小石子作為計算工具,並用減半和加倍兩種運算就能求得任何兩個整數的乘積。其規則是 左邊不斷除2,寫下商,捨去餘數 右邊不斷加倍,直到左邊...