bzoj 1106 貪心 樹狀陣列 或 棧模擬

2021-07-27 23:36:30 字數 2474 閱讀 1802

題意:n個數,各出現兩次,當兩個相同的數相鄰時,這兩個數同時消除,上方的方塊同時下落且可繼續消除滿足條件的。每次可交換相鄰的兩個方塊,求最少交換次數使得所有數全消除

首先,對於一對相同的數中間有另一對的情況(即兩對相同的數是巢狀關係),肯定要先消除另一對

其次,對於一對相同的數中間有另一對中的乙個的情況(即兩對相同的數有交集),先消除哪個其實是一樣的(把一對換到另一對外或把另一對換到這一對裡是等價的)

那麼我們有兩種實現方式:

(1)方法一

棧模擬我們上述過程,如果乙個元素已經出現在棧裡,找出並刪除同時進行維護,對答案的貢獻就是兩個位置中間棧的元素數,即 top-i (i為第一次出現的位置在棧中位置)

var

n,x,top,ans :longint;

vis :array[0..50010] of boolean;

z :array[0..100010] of longint;

i :longint;

procedure find(x,pos:longint);

var i,j:longint;

begin

for i:=top downto 1 do

if z[i]=x then break;

inc(ans,top-i);

for j:=i to top-1 do z[j]:=z[j+1];

dec(top);

end;

begin

read(n);

for i:=1 to 2*n do

begin

read(x);

if not vis[x] then

begin

vis[x]:=true;

inc(top); z[top]:=x;

end else find(x,i);

end;

writeln(ans);

end.

經親測

(2)方法二

依次讀入的時候,如果是第二次出現,那麼就把它和第一次出現的位置合併,那麼必須交換的次數為(second-first-1)即兩者之間的距離,證明見上分類。用樹狀陣列維護即可

var

n,x,ans :longint;

i :longint;

first :array[0..50010] of longint;

t :array[0..100010] of longint;

function lowbit(x:longint):longint;

begin

exit(x and (-x));

end;

procedure add(x,v:longint);

begin

while (x<=n*2) do

begin

inc(t[x],v);

inc(x,lowbit(x));

end;

end;

function find(x:longint):longint;

var ans:longint;

begin

ans:=0;

while (x>0) do

begin

inc(ans,t[x]);

dec(x,lowbit(x));

end;

exit(ans);

end;

begin

read(n); ans:=0;

for i:=1 to n*2 do

begin

read(x);

if first[x]=0 then

begin

first[x]:=i;

add(i,1);

end else

begin

inc(ans,find(i)-find(first[x]-1)-1);

add(first[x],-1);

end;

end;

writeln(ans);

end.

經親測

兩種方法的思路是一樣的,即對答案的貢獻為第一次位置和第二次位置之間的距離(中間的滿足條件的消除後的),只是維護的方法不一樣而已

第一種用到棧頂的距離維護,第二種用樹狀陣列維護

bzoj1246(樹狀陣列)

樹狀陣列的靈活運用,維護的是最大值,因為整個陣列就是乙個字首最大值,所以可以用實現,求乙個字首最大值,和更新pos之後的最大值。很好的運用,多回顧思考 include include include include includeusing namespace std const int n 200...

bzoj 2762 樹狀陣列

題意 給出一些形如 ax b 1 新加入乙個不等式 2 刪除乙個不等式 3 詢問當x k時滿足的不等式的個數 對於每乙個不等式,通過變形就可以得到使它成立的x的範圍 那麼就變成區間修改,單點查詢,樹狀陣列維護就好 注意 1 討論a 0 a 0 a 0的情況 2 由於k有非正數,所以要加上10 6 1...

bzoj 1935(樹狀陣列)

傳送門 題解 由於是靜態問題所以可以離線處理,所有點 詢問拆成4個 按x排序,二維可以轉成一維,相當於每次query到的就是當前已插入的點,而只有這些點能對query的返回值造成貢獻。p.s.對於x座標相同的插入 詢問,要考慮這幾個操作的先後順序 include using namespace st...