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操...