一節政治課的結果……推式子+推式子+推式子……
首先注意到乙個區間裡面,選擇(x, y)和(y, x)的費用是一樣的。所以我們把這兩種情況合為一種,那麼現在詢問的區間為(l, r),則一共的情況就有 1 / (k + 1)*(k)種 (k = r - l + 1)。所以我們只需要求出區間內所有的子集之和 * 2 / (k + 1) * k(每種情況有兩種)。但這樣複雜度還是太高了,我們考慮繼續推下式子。
順著乙個比較常見的思路想:分離出每一段路對於答案的貢獻再累加起來。那麼我們的ans = vx(這一段路的代價) * 包含了這條道路的區間個數。包含了第x條道路的區間個數一共是(x - l + 1) * (r - x)。但這個東西我們不好維護,所以將它拆分一下,盡量分離出不變的量。這個東西就等於:((rx + lx) - (x * x + x) + (r - l * r))* vx。由此, 問題轉化為維護區間內的 vx 之和, vx * x之和, 與 vx * x * (x + 1)之和。線段樹完美解決!
//luogu-judger-enable-o2
#include using
namespace
std;
#define maxn 100005
#define int unsigned long long
int n, m, mark[maxn * 3
];struct
tree
t[maxn * 40
];int
read()
while(c >= '
0' && c <= '
9') x = x * 10 + c - '
0', c =getchar();
return x *k;
}void build(int p, int l, int
r)
int mid = (l + r) >> 1
; build(p
<< 1, l, mid), build(p << 1 | 1, mid + 1
, r);
t[p].x = t[p << 1].x + t[p << 1 | 1
].x;
t[p].xx = t[p << 1].xx + t[p << 1 | 1
].xx;
return;}
void push_up(int p, int
num)
void push_down(int
p)void update(int p, int l, int r, int num) //
num1 :vx * x, num2 :vx * x * (x + 1), num3 : vx;
if(r < l || l > r) return
; push_down(p);
update(p
<< 1, l, r, num), update(p << 1 | 1
, l, r, num);
t[p].num[
1] = t[p << 1].num[1] + t[p << 1 | 1].num[1
]; t[p].num[
2] = t[p << 1].num[2] + t[p << 1 | 1].num[2
]; t[p].num[
3] = t[p << 1].num[3] + t[p << 1 | 1].num[3];}
int query(int p, int l, int r, int
opt)
int get(int a, int
b)
returna;}
signed main()
else
//num1 :vx * x, num2 :vx * x * (x + 1), num3 : vx;
}return0;
}
HAOI2012 高速公路
輸入檔案 roadxw.in輸出檔案 roadxw.out簡單對比 時間限制 2 s 記憶體限制 2560 mb 時間限制 2秒 輸入 road.in 輸出 road.out y901高速公路是一條重要的交通紐帶,部門建設初期的投入以及使用期間的養護費用都不低,因此 在這條高速公路上設立了許多收費站...
HAOI2012 高速公路 線段樹
考慮每乙個詢問答案的分子 用線段樹維護序列,每個節點記錄以下內容 這樣就可以對區間進行 o 1 的快速合併 考慮如何下傳標記,設要放置的標記值為 t 則 include using namespace std define int long long const int n 1000005 int ...
ccf 高速公路
問題描述 某國有n個城市,為了使得城市間的交通更便利,該國國王打算在城市之間修一些高速公路,由於經費限制,國王打算第一階段先在部分城市之間修一些單向的高速公路。現在,大臣們幫國王擬了乙個修高速公路的計畫。看了計畫後,國王發現,有些城市之間可以通過高速公路直接 不經過其他城市 或間接 經過乙個或多個其...