NOI2007 項鍊工廠

2022-03-03 12:36:11 字數 1795 閱讀 3876

60pts

有一點容易寫錯的小細節:

比如說求全域性的段數的時候,如果只有一種顏色,那麼當左右端點相等時,就不要ans--了。

注意右端點小於左端點的情況。

#include#include#include#include#include#define maxn 2010

using namespace std;

int n,m,q;

int c[maxn],tmp[maxn];

namespace subtask1

for(int i=1;i<=n;i++) c[i]=tmp[i];

}else if(s[0]=='f')

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

for(int i=1;i<=n;i++) c[i+n]=c[i];

} }

}using namespace subtask1;

int main()

100pts

如果沒有翻轉和旋轉,很顯然可以用線段樹維護合併,更改和查詢都是log的級別的。

但是旋轉的話,我們可以通過記錄乙個變數,從而還原該操作在原先環中的位置。

然後觀察翻轉——通過繪圖我們發現,翻轉之後的環的順時針移動翻轉回來相當於原先的環的逆時針移動——所以我們就可以還原位置了。

我們把當前需要處理的位置,還原成它原本的位置上的編號,然後用線段樹維護一下更新和查詢就行了。

#include#include#include#include#include#include#define maxn 500010

using namespace std;

int n,m,q,rev,kkk;

char s[5];

struct nodet[maxn<<2];

inline int ls(int x)

inline int rs(int x)

inline void push_up(int x)

inline void build(int x,int l,int r)

int mid=(l+r)>>1;

build(ls(x),l,mid);

build(rs(x),mid+1,r);

push_up(x);

}inline void f(int x,int k)

inline void push_down(int x)

}inline void update(int x,int ll,int rr,int k)

push_down(x);

int mid=(l+r)>>1;

if(ll<=mid) update(ls(x),ll,rr,k);

if(mid>1;

if(rr<=mid) return query(ls(x),ll,rr);

if(ll>mid) return query(rs(x),ll,rr);

else

}inline int pos(int x)

inline int calc(int x,int l,int r,int k)

int main()

else if(s[0]=='f')

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

else if(s[0]=='p')

else if(strlen(s)>1&&s[0]=='c'&&s[1]=='s')

}else

}return 0;

}

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 函式...

bzoj1493 NOI2007 項鍊工廠

維護全域性移動量什麼的後可以上線段樹。思維難度低一點的做法是直接splay。適合我這種腦殘選手 f操作就是把2 n翻轉。r操作就是把後面k個元素插到最前面來。維護顏色段是老套路了。比較坑的是。多加倆邊界節點的話,需要考慮有沒有可能對答案造成影響。然而邊界節點不可能在合併子區間的時候造成干擾。而且p操...