LG2154 SDOI2009 虔誠的墓主人

2022-05-07 19:51:08 字數 1434 閱讀 1756

洛谷

如果您沒有看懂題,請反覆閱讀題面及樣例

可以發現,對於某乙個點,它的答案就是上下左右幾個組合數乘起來。

這樣直接做複雜度顯然**,考慮怎麼優化這個東西。

我們可以固定左右,在某兩個左右之間維護上下有多少個,這樣子的話左右的貢獻就是不變的,而且你最多隻會變化\(o(n)\)次左右邊界,複雜度***。

這樣的話,每次查詢乙個左右邊界內上下的貢獻,用線段樹維護即可。(描述可能有些模糊,具體詳見**)

#include #include #include #include #include #include #include using namespace std; 

inline int gi()

const int max_n = 1e5 + 5;

#define lson (o << 1)

#define rson (o << 1 | 1)

int sum[max_n << 2];

void modify(int o, int l, int r, int pos, int v)

int query(int o, int l, int r, int ql, int qr)

int w, h, n, k;

int x[max_n], y[max_n], ox[max_n], oy[max_n], tx, ty;

vectorvec[max_n];

int c[max_n][15], c1[max_n], c2[max_n];

bool cmp(const int &l, const int &r)

int main ()

for (int i = 1; i <= n; i++) vec[x[i]].push_back(i), c1[y[i]]++;

for (int i = 1; i <= tx; i++) vec[i].push_back(n + 1);

y[n + 1] = ty + 1;

for (int i = 1; i <= tx; i++) sort(vec[i].begin(), vec[i].end(), cmp);

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

for (int i = 1; i <= n; i++)

for (int j = 1; j <= min(i, k); j++)

c[i][j] = c[i - 1][j] + c[i - 1][j - 1];

int ans = 0;

for (int i = 1; i <= tx; i++)

} if (ans < 0) ans += 2147483648ll;

printf("%d\n", ans);

return 0;

}

SDOI2009 虔誠的墓主人

題目大意 n times m 的點陣,有的點是樹木,定義乙個空點的度數為正上,正左,正右,正下分別有 k 個點的選法 求點陣的總度數.挺好的一道題,排列組合和資料結構糅合在一塊 include include include define lowbit x x x 巨集定義樹狀陣列操作 using ...

洛谷 SDOI2009 虔誠的墓主人

初見安 這裡是傳送門 洛谷p2154 sdoi2009 虔誠的墓主人 題意很簡單 在n m的網格上,求所有未標記點的權值和。乙個未標記點的權值為 設其上下左右有 首先資料範圍很夠,k很小,我們就預處理 暴力做法列舉每個格點的話,我們可以預處理出每行每列標記點的字首和然後離散化,這樣的話複雜度就是 我...

SDOI2009 HH的項鍊 題解

題意 給乙個序列,長度為n,再給m個詢問,對每個詢問,輸出這個區間內有多少個不同的數。其實只需要把最後乙個出現的數統計一下就可以了,因為只有最後乙個出現的那個數才是有價值的,之前重複的數可以忽略,由此,演算法的框架就出來了,只需要有cdq的思想把查詢以區間的右端點為關鍵字排序,從前到後,同時用新出現...