[bzoj2388]旅行規劃
試題描述
oivillage是乙個風景秀美的鄉村,為了更好的利用當地的旅遊資源,吸引遊客,推動經濟發展,xkszltl決定修建了一條鐵路將當地n個最著名的經典連線起來,讓遊客可以通過火車從鐵路起點(1號景點)出發,依次遊覽每個景區。為了更好的評價這條鐵路,xkszltl為每乙個景區都哦賦予了乙個美觀度,而一條旅行路徑的價值就是它所經過的景區的美觀度之和。不過,隨著天氣與季節的變化,某些景點的美觀度也會發生變化。
xkszltl希望為每位旅客提供最佳的旅行指導,但是由於遊客的時間有限,不一定能遊覽全部景區,然而他們也不希望旅途過於短暫,所以每個遊客都希望能在某乙個區間內的車站結束旅程,而xkszltl的任務就是為他們選擇乙個終點使得旅行線路的價值最大。可是當地的景點與前來觀光的旅客實在是太多了,xkszltl無法及時完成任務,於是找到了準備虐殺noi2011的你,希望你能幫助他完成這個艱鉅的任務。
輸入
第一行給出乙個整數n,接下來一行給出n的景區的初始美觀度。
第三行給出乙個整數m,接下來m行每行為一條指令:
1. 0 x y k:表示將x到y這段鐵路邊上的景區的美觀度加上k;
2. 1 x y:表示有一名旅客想要在x到y這段(含x與y)中的某一站下車,你需要告訴他最大的旅行價值。
輸出
對於每個詢問,輸出乙個整數表示最大的旅行價值。
輸入示例
518 -8
3 -731
1501
3612
4
輸出示例
922
資料規模及約定
對於20%的資料,n,m≤3000;
對於40%的資料,n,m≤30000;
對於50%的資料,n,m≤50000;
另外20%的資料,n,m≤100000,修改操作≤20;
對於100%的資料,n,m≤100000。
題解
這題就是讓維護區間最大字首和(字首和左端點為 1)。那麼我們不妨就維護這個字首和。
那麼區間 [l, r] 的修改操作就變成了從第 l 個數開始,依次給每個位置加上 k, 2k, 3k, ... , (r-l+1)k。
查詢操作就是詢問區間最大值。
我們對序列分塊。考慮修改操作,對於整塊的我們打兩個懶標記:addv[i] 表示這一塊中的所有數增加 addv[i] 的值;k[i] 表示這一塊中增加的等差數列的公差,即這一塊中的元素在加完 addv[i] 後依次要加上 k[i], 2k[i], 3k[i], ... , siz · k[i]。再想想詢問如何處理,對於整塊的詢問相當於就是找到 max(st[i] 和 en[i] 表示第 i 個塊的起始和終點位置),我們發現如果把 (x - st[i] + 1, s[x]) 當作座標系上的點,那麼詢問就相當於用一條斜率為 -k[i] 的直線去碰那個點,要求找到最大的截距,解決這個問題維護凸包即可。
注意當 k[i] 和 addv[i] 變化時(即整塊都被修改),不需要重新維護凸包形態(想一想,為什麼)。
#include #include #include #include #include #include #include using namespace std;const int buffersize = 1 << 16;
char buffer[buffersize], *head, *tail;
inline char getchar()
return *head++;
}int read()
while(isdigit(c))
return x * f;
}#define maxn 100010
#define maxbl 320
#define oo (1ll << 60)
#define ll long long
int n, cb, st[maxbl], en[maxbl], blid[maxn];
ll sa[maxn], addv[maxbl], k[maxbl], cp[maxbl];
struct vec
vec(ll _, ll __): x(_), y(__) {}
vec operator + (const vec& t) const
vec operator - (const vec& t) const
ll operator ^ (const vec& t) const
} poly[maxbl][maxbl];
void pushdown(int bl)
void build_poly(int bl)
return ;
}void update(int ql, int qr, int k)
else
} for(int i = blid[qr] + 1; i <= cb; i++) addv[i] += (ll)k * (qr - ql + 1);
return ;
}ll getans(int bl, int p)
ll query(int ql, int qr)
int b = blid[ql];
pushdown(b); build_poly(b);
for(int i = ql; i <= en[b]; i++) ans = max(ans, sa[i]);
b = blid[qr];
pushdown(b); build_poly(b);
for(int i = st[b]; i <= qr; i++) ans = max(ans, sa[i]);
for(int i = blid[ql] + 1; i <= blid[qr] - 1; i++)
ans = max(ans, getans(i, l)); }
return ans;
}int main()
for(int i = 1; i <= cb; i++) build_poly(i);
int q = read();
while(q--)
else }
return 0;
}
分塊打起來好爽 ^_^
BZOJ2388 旅行規劃
分塊,每一塊維護字首和,觀察發現,一次區間加操作對於 l 前,r後的區間裡相對的大小關係沒有影響,對於 l r 裡,將每個位置放在平面內作為乙個點 i si 那麼相當於給區間裡加了乙個斜率。每個塊維護乙個凸包 上凸下凸應該都可以,下文以上凸為例 如果這個塊被完整覆蓋,就打個斜率的標記,否則暴力重構凸...
bzoj2388 旅行規劃
凸包好題 我一開始想的是線段樹或平衡樹維護最大字首和,但是區間修改很噁心,後來想分塊,發現貌似可以做,修改的話,中間的塊打標記,兩邊的暴力重構,查詢的話就是整塊二分斜率為零的地方,邊上的暴力查詢。o nsqrt n log n 1 include 2 include 3 include 4 incl...
BZOJ2388 旅行規劃
bzoj2388 旅行規劃 又是一道氪金題。bzoj 氪金無極限。附上大美洛谷的題面 洛谷p4192 旅行規劃 oivillage是乙個風景秀美的鄉村,為了更好的利用當地的旅遊資源,吸引遊客,推動經濟發展,xkszltl決定修建了一條鐵路將當地n個最著名的經典連線起來,讓遊客可以通過火車從鐵路起點 ...