NOI2007T4 項鍊工廠 線段樹 座標變換

2021-07-28 11:19:37 字數 1883 閱讀 3289

做法:之前沒想出座標變換的規律性,於是用splay做,寫了300+行,慘跪......現在回來一想,這不就是道線段樹嘛!結果換線段樹後只有200行左右,果然線段樹還是區間處理的大殺器。

我們設乙個座標的對映序列s,s[i]就是當前標號為i的珠子最原始的標號,我們發現無論怎麼旋轉、翻轉,這個序列都是乙個環序列,即一定存在某乙個位置x,將其右邊的所有元素接到所有元素的左邊,形成的序列為或者。這樣我們就可以用兩個引數來表示當前對映序列的狀態:乙個是當前標號為1的珠子最原始的標號,乙個是反映當前的環序列經過切割再接之後的序列是還是。於是對於每個旋轉操作,改變的是第乙個引數,對於每個翻轉操作,改變的是第二個引數,修改的時間都是o(1)的。而且,我們可以由這兩個引數用o(1)時間算出當前的對映序列上某乙個元素的值。這時我們就可以用線段樹來維護環上的顏色,這樣對於每個詢問和修改操作,就可以用o(logn)的時間維護了。

然而還有要注意的小細節,一是在環上連續的一段依靠對映序列對映到原序列上時,並不一定也是連續的一段,可能是由頭和尾的兩端拼接而成,這時候要特別注意詢問的方法以及頭和尾的元素是否相等,以免出現計數錯誤。二是在c操作中,正常情況下詢問得到結果後我們會判斷頭尾兩個元素是否相等,如果相等結果減1,但如果整個環只有乙個顏色,那麼按以上步驟處理完後結果就是0,這不符合要求,所以當詢問後得到的結果是1就不用再比較了。

以下是本人**:

#include #include #include #include using namespace std;

int n,c,a[500010],q,fir=0,lft,rht,ans;

bool fliped=0;

struct smt

seg[2000010];

void pushdown(int no)

}void pushup(int no)

void buildtree(int no,int l,int r)

buildtree(no<<1,l,mid);

buildtree(no<<1|1,mid+1,r);

pushup(no);

}int query(int no,int l,int r,int x)

void modify(int no,int l,int r,int s,int t,int x)

pushdown(no);

if (s<=mid) modify(no<<1,l,mid,s,t,x);

if (t>mid) modify(no<<1|1,mid+1,r,s,t,x);

pushup(no);

}int count(int no,int l,int r,int s,int t)

pushdown(no);

if (s<=mid) sum+=count(no<<1,l,mid,s,t);

if (t>mid) sum+=count(no<<1|1,mid+1,r,s,t);

return sum;

}int main()

if (op[0]=='f') fliped=!fliped;

if (op[0]=='s')

else

ca=query(1,1,n,posa);

cb=query(1,1,n,posb);

modify(1,1,n,posa,posa,cb);

modify(1,1,n,posb,posb,ca);

} if (op[0]=='p')

}else

}} if (op[0]=='c'&&op[1]!='s')

if (op[0]=='c'&&op[1]=='s')

if (!fliped)

}else

}printf("%d\n",ans);

} }

return 0;

}

NOI2007 項鍊工廠

60pts 有一點容易寫錯的小細節 比如說求全域性的段數的時候,如果只有一種顏色,那麼當左右端點相等時,就不要ans 了。注意右端點小於左端點的情況。include include include include include define maxn 2010 using namespace st...

1493 NOI2007 項鍊工廠

線段樹。真還就是個線段樹。除去操作1,2的話,線段樹很容易就處理了,問題在於如何處理操作1和2。這點沒想到 我們用乙個delta維護操作1,如果沒有旋轉就 k,不然就 k。每次讀入i和j的時候用trans處理一下,就成功在o 1 的時間解決了操作1和2。細節很重要。include include i...

BZOJ1493 NOI2007 項鍊工廠

原題位址 又是一道資料結構神題,卡了一晚上 寫一下其中幾個寫搓的地方 1.update 時要clear 左右子樹 2.查詢完之後要記得把樹merge 回去 3.交換操作那裡,若i,j相等則直接退出,要不然會出錯 4.染色 查詢操作l r和l r時split 的範圍不同 update split 函式...