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