poj 3225 間隙 橫截面和填充操作

2021-09-22 09:43:53 字數 3697 閱讀 8947

一道題又做了一天。

。這道題對我來說起初有n多難點。

1:區間的開閉怎樣解決。

2:如何把區間的交並補、對稱差轉化為對線段樹的操作。

後來與實驗室的同學討論了後攻克了前面兩個問題。

對於區間的開閉,能夠將區間放大一倍,偶數點表示端點。奇數點表示區間內線段,前開的話左端點加1,右開的話右端點減1。比如[1,3]能夠表示成[2,6],(1,3)表示成(3,5)。

對於區間的交並補問題,能夠轉化為區間覆蓋問題。若t區間為[a,b]。

u t:[a,b]覆蓋為1.

i t:[0,a-1] [b+1,maxn] 覆蓋為0

d t:[a,b]覆蓋為0

c t:[0,a-1] [b+1,maxn] 覆蓋為0,[a,b]取反

s t:[a,b]取反

然後處理區間的覆蓋和異或操作。

起初對異或操作沒想到lazy,考慮到異或的性質。兩次異或相當於沒變。所以節點附加兩個資訊:col,rev。

col表示覆蓋資訊,col=0說明全被覆蓋為0。col=1說明全被覆蓋為1,col=-1說明沒有全被覆蓋。

rev表示異或資訊,rev=1說明區間總體異或,rev=0說明不用異或。

可見僅僅有當col=-1時rev才實用。更新時。若是區間覆蓋,對應區間覆蓋後抹去異或操作。若是異或操作,推斷區間是否全然覆蓋。若是直接異或,否則rev進行異或。push_down的時候,若區間全然覆蓋,將覆蓋資訊推送下去並將左右兒子的異或操作抹去,若區間沒有全然覆蓋,必然有異或操作,將左右兒子能夠異或的異或掉,不能異或的將其rev異或。

#include #include #include #include #include #include #include #include #include #include #include #include #include //#define ll long long

#define ll __int64

#define eps 1e-12

#define pi acos(-1.0)

using namespace std;

const int inf = 0x3f3f3f3f;

const int maxn = 131072;

struct node

tree[maxn*4];

char s1[10],s2[10];

int a[maxn+10];

void build(int v, int l, int r)

void push_down(int v)

if(tree[v].rev) //區間沒被全然覆蓋且須要異或

} void update(int v, int l, int r, int col) else return; } push_down(v); int mid = (tree[v].l + tree[v].r) >> 1; if(r <= mid) update(v*2,l,r,col); else if(l > mid) update(v*2+1,l,r,col); else } void query(int v) if(tree[v].col == 0) return; if(tree[v].l == tree[v].r) return; push_down(v); query(v*2); query(v*2+1); } int main() else if(s1[0] == 'i') else if(s1[0] == 'd') else if(s1[0] == 'c') else } query(1); int flag = 0; for(int i = 0; i < maxn; i++) } if(flag == 0) printf("empty set\n"); else printf("\n"); return 0; }

做了hdu 3379,又嘗試了一種寫法,就是將上面的col和rev合併起來,由於它們是相互排斥的,乙個節點僅僅會有乙個資訊。

所以僅僅用col表示。col為2時表示取反。為-1表示不操作。若開始是-1,當兩次取反後又變回-1。

#include #include #include #include #include #include #include #include #include #include #include #include #include //#define ll long long

#define ll __int64

#define eps 1e-12

#define pi acos(-1.0)

using namespace std;

const int inf = 0x3f3f3f3f;

const int maxn = 131072;

struct node

tree[maxn*4];

char s1[10],s2[10];

int a[maxn+10];

void build(int v, int l, int r)

void push_down(int v)

else

tree[v].col = -1;

return;

}void update(int v, int l, int r, int col)

else

return;

} push_down(v);

int mid = (tree[v].l + tree[v].r) >> 1;

if(r <= mid)

update(v*2,l,r,col);

else if(l > mid)

update(v*2+1,l,r,col);

else }

void query(int v)

if(tree[v].col == 0)

return;

if(tree[v].l == tree[v].r)

return;

push_down(v);

query(v*2);

query(v*2+1);

}int main()

else if(s1[0] == 'i')

else if(s1[0] == 'd')

else if(s1[0] == 'c')

else

}query(1);

int flag = 0;

for(int i = 0; i < maxn; i++) }

if(flag == 0)

printf("empty set\n");

else printf("\n");

return 0;

}

POJ 3225 區間操作 交並補

u 把區間 l,r 覆蓋成1 i 把 l r,覆蓋成0 d 把區間 l,r 覆蓋成0 c 把 l r,覆蓋成0 且 l,r 區間0 1互換 s l,r 區間0 1互換 cover記錄成段覆蓋,xo記錄互換 當乙個節點得到覆蓋標記時把異或標記清空 當乙個節點得到異或標記的時候,先判斷覆蓋標記,如果是0...

poj 3225 關於集合運算

1.關於集合運算的推導規約,知道集合是什麼東西就一定會推導!u 把區間 l,r 覆蓋成1 i 把 l r,覆蓋成0 d 把區間 l,r 覆蓋成0 c 把 l r,覆蓋成0 且 l,r 區間0 1互換 s l,r 區間0 1互換 2.倍化區間處理開閉區間的問題 因為普通的線段樹實際處理的並非真正的區間...

poj 3485 區間選點

題意 x軸上公路從0到l,x軸上下有一些點給出座標代表村莊,問在公路上最少建幾個出口才能使每個村莊到出口的距離不超過d。以村莊為圓心,半徑為 d 畫圓,與公路相交,得到乙個乙個區間,這麼選點呢?按照區間右端點排序,第乙個點,選擇第一條線段的右端點,當前位置就在這裡,已經 很 靠後了,拿這個點去檢視以...