HOJ2965 Magic Pen4 解題報告

2021-06-08 07:06:27 字數 1601 閱讀 9990

brief description:

給定n條線段以及整數k,線段上有乙個顏色值num,現在有2種操作,0,x,y:將x到y的線段的(num值+1)%k,1,x,y:求x到y被num值劃分為多少個部分(連續的相同num值為乙個部分)。

analysis:

這題顯然用線段樹做,我們根據問題的特點設計線段樹節點的域。

線段樹節點域為:

struct nodett[maxn*4];

ll(idx): idx的左兒子,rr(idx):idx的右兒子

lcol:最左邊的點的顏色,  rcol:最右邊的點的顏色,add:延遲標記(祖先的加和),sum:本段有多少個部分。

每次push_up到父節點的時候,tt[idx].sum = tt[ll(idx)].sum + tt[rr(idx)].sum;再判斷tt[ll(idx)].rcol與tt[rr(idx)].lcol是否模k同餘,若同餘,tt[idx].sum--

這個是經典的「區間更新,區間查詢」的模型,區間合併的關鍵細節還是見**吧:

"區間更新,區間查詢",push_down和push_up是很關鍵的操作,update時的push_up注意「延遲操作」的更新。

#include #include #include #include #include #include #define ll(x) ((x)<<1)

#define rr(x) ((x)<<1|1)

using namespace std;

const int maxn = 100010;

struct nodett[maxn*4];

int n,m,mm;

void build(int left,int right,int idx)

void push_up(int idx,int l1,int r1)

void update(int left,int right,int idx)

tt[idx].add = 0;

return;

}if(tt[idx].add)

int mid = (tt[idx].left + tt[idx].right)>>1;

if(left <= mid)

if(mid < right)

/*important code*/

int l1 = tt[ll(idx)].add,r1 = tt[rr(idx)].add;

push_up(idx,l1,r1);

}int query(int left,int right,int idx)

tt[idx].lcol += tt[idx].add; tt[idx].rcol += tt[idx].add;

tt[idx].add = 0;

}if(left==tt[idx].left && right==tt[idx].right)

int mid = (tt[idx].left + tt[idx].right) >> 1,ret;

if(right <= mid)else if(left > mid)else

}int main()

}return 0;

}

poj 2965 解題報告

就是對乙個4x4的棋盤進行翻轉,每一次翻轉都將讓同一行和列一起翻轉,直到所有符號都變為 時成功。通過列舉加上深度優先搜尋的方法進行解決,列舉通過行號和列號順序進行,每個位置都有翻轉和不翻轉兩種選擇 通過乙個位置兩次翻轉來回溯 poj 2965 244k 844ms include using nam...

poj 2965 遞迴 列舉

本題與1753思路一樣,區別就在於要記錄位置。deep是當前進行到了哪一步,step是判斷用step步是否可以完成,因此記錄位置只需在change 後做,回溯的時候雖然會說明上一步無效,但不用修改記錄,因為下一次記錄會覆蓋它。include using namespace std bool map ...

poj2965解題報告

這道題目的思路和 url 的思路一樣。有所不同的是這道題目中還需要輸出搜尋的路徑,於是在unit中加了乙個pre變數以記錄搜尋的路徑,最後通過遞迴呼叫print detail從前往後輸出寬搜的結果。problem 2965 user godfrey90 memory 1992k time 1000m...