洛谷
如果您沒有看懂題,請反覆閱讀題面及樣例
可以發現,對於某乙個點,它的答案就是上下左右幾個組合數乘起來。
這樣直接做複雜度顯然**,考慮怎麼優化這個東西。
我們可以固定左右,在某兩個左右之間維護上下有多少個,這樣子的話左右的貢獻就是不變的,而且你最多隻會變化\(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的思想把查詢以區間的右端點為關鍵字排序,從前到後,同時用新出現...