毒瘤分块题
作者:互联网
[Ynoi]2018 末日时...
好了,这题上来想构造一种新型的线段树,维护前缀,但后来发现最大字段和的性质太毒瘤了,然后直接自闭。
只好进入题解,看了一下shadowice的题解
哇shadowice太神仙了
闵可夫斯基珂并凸包
然后学了一下闵可夫斯基珂并凸包
主要讲如何快速合并凸包A,B
我们先求出点集A的上凸壳和点集B的上凸壳
然后构造一个网格图
接下来我们维护两个指针i,j表示在网格图上走到了(i,j)这个点
首先先将(1,1)加入点集
然后选择点(i+1,j)与(i,j)的斜率和点(i,j+1)与点(i,j)间的斜率较大的一组走
如果一侧已经无路可走就一直沿着另一侧走到底
合并完成
Jarvis水平步进法求凸包
1 找到位于最低最左边的点$p_0$,最高最右边的点$p_k$,则此两点必为凸包上的点。
2 对逆时针方向排列的顶点序列按$p_0$->$p_k$构造右链,左链。
3 设定一个栈,先将$p_0$入栈,对其他的点依据相对于栈顶元素的最小极角,并距离最远的点入栈,左链同理。
求相对于栈顶元素的最小极角
设$p_{top}$为最高点,$p_0$位栈顶元素;
只要栈顶元素不是$p_{top}$,循环做以下工作:
依次考查其他的点$p_i$,是否有相对于$p_{top}$的最小极角
贴个代码:基本上完全照着shadowice巨佬打的QAQ
//refer to shadowice1984's solution //Compiler optimization #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #include <cstdio> //type define #define ll long long //function define #define min(a,b) ((a<b)?a:b) #define max(a,b) ((a>b)?a:b) //NUM define const ll _MIN = (-(1ll << 47)); #define MAXN 100010 #define BLK_SIZE 110 #define BLK_NUM 1005 inline int readInt(){ int x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } inline ll readLL(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } struct Point{ ll x, y; }; Point operator + (const Point &a, const Point &b){ return (Point){a.x + b.x, a.y + b.y}; } inline bool CompVal(const Point &a, const Point &b, const ll &c){ return ((b.x - a.x) * c >= b.y - a.y); } inline bool Comp3(const Point &a, const Point &b, const Point &c){ return ((a.x - b.x) * (a.y - c.y) >= (a.y - b.y) * (a.x - c.x)); } inline bool Comp4(const Point &a, const Point &b, const Point &c, const Point &d){ return ((a.x - b.x) * (c.y - d.y) >= (a.y - b.y) * (c.x - d.x)); } struct MSS{ ll sum, l, r, ans; }; MSS operator + (const MSS &a, const MSS &b){ return (MSS){a.sum + b.sum, max(a.sum + b.l, a.l), max(a.r + b.sum, b.r), max(a.r + b.l, max(a.ans, b.ans))}; } Point stk[BLK_SIZE + 1]; ll asum[BLK_SIZE + 1]; void getCH(Point *stk, int &top){ //get convex hull int i, r; for(i = 2, r = top, top = 1; i <= r; ++i){ while(top > 1 && Comp3(stk[top - 1], stk[top], stk[i])) --top; stk[++top] = stk[i]; } } inline void insert(const Point &a){ stk[a.x].y = max(stk[a.x].y, a.y); } struct Block{ //threshold of caculate directly #define direct_ts 16 //Member in long long ll a[BLK_SIZE + 1], add_val; ll thre_val; //Member in int int sz; //pre-[pre-suf-ans] int p1, p2, p3; //suf-[pr-suf-ans] int s1, s2, s3; //Member in MSS MSS val; //Membet in Point Point ans[BLK_SIZE + 1]; // prefix suffix Point pre[BLK_SIZE + 1], suf[BLK_SIZE + 1]; //Member in bool bool flg; //Functions //caculate directly inline int sol_direct(int l, int r){ ll tot = 0; for(int i = l + 1; i <= r; ++i) tot += a[i], ans[i] = (Point){i - l, tot}; for(int i = l + 2; i <= r; ++i){ tot = 0; Point* _new = ans + l + 1; for(int j = i; j <= r; ++j, ++_new) tot += a[j], _new->y = max(_new->y, tot); } s3 = r - l; getCH(ans + l, s3); return s3; } //caculate int sol(int l, int r){ if(r - l < thre_val) return 0; if(r - l <= direct_ts) return sol_direct(l, r); int mid = (l + r) >> 1; int resl = sol(l, mid), resr = sol(mid, r); for(int i = 1; i <= r - l; ++i) stk[i] = (Point){i, _MIN}; for(int i = l + 1; i <= l + resl; ++i) insert(ans[i]); for(int i = mid + 1; i <= mid + resr; ++i) insert(ans[i]); ll tot = 0; s1 = 0; for(int i = mid + 1; i <= r; ++i) ++s1, tot += a[i], pre[s1] = (Point){s1, tot}; getCH(pre, s1); tot = 0, s2 = 0; for(int i = mid; i > l; --i) ++s2, tot += a[i], suf[s2] = (Point){s2, tot}; getCH(suf, s2); //merge Convex Hull //go both direction int i = 1, j = 1; insert(pre[i] + suf[j]); for(; i != s1 && j != s2;){ if (Comp4(pre[i], pre[i + 1], suf[j], suf[j + 1])) ++j; else ++i; insert(pre[i] + suf[j]); } //go along one direction if(i != s1) for(++i; i <= s1; ++i) insert(pre[i] + suf[j]); if(j != s2) for(++j; j <= s2; ++j) insert(pre[i] + suf[j]); s3 = r - l; getCH(stk, s3); for(int i = 1; i <= s3; ++i) ans[l + i] = stk[i]; return s3; } inline void movP(Point *a, int &pos, int &t){ while(pos != t) if(CompVal(a[pos], a[pos + 1], -add_val)) break; else ++pos; } void build(){ //Make convex hull for (int i = 1; i <= sz; ++i) a[i] += add_val; add_val = 0; if (!flg){ //refresh flg flg = 1; for (int i = 1; i <= sz; ++i) flg = flg && (a[i] >= 0ll); } if (flg){ val.sum = 0; for (int i = 1; i <= sz; ++i) val.sum += a[i]; val.l = val.r = val.ans = val.sum; return ; } thre_val = ans[p3].x, sol(0ll, sz); ll tot = 0ll; s1 = 0ll; for (int i = 1; i <= sz; ++i) ++s1, tot += a[i], pre[s1] = (Point){s1, tot}; getCH(pre, s1); tot = 0ll, s2 = 0ll; for (int i = sz; i >= 1; --i) ++s2, tot += a[i], suf[s2] = (Point){s2, tot}; getCH(suf, s2); p1 = 1, movP(pre, p1, s1); p2 = 1, movP(suf, p2, s2); p3 = 1, movP(ans, p3, s3); //refresh flg again flg &= (bool)((p1 == s1) && (p2 == s2) && (p3 == s3)); //refresh val val = (MSS){tot, max(pre[p1].y, 0ll), max(suf[p2].y, 0ll), max(ans[p3].y, 0ll)}; } void add(ll x){ if (flg){ add_val += x; val.sum += sz * x; val.l = val.r = val.ans = val.sum; return ; } add_val += x; movP(pre, p1, s1), movP(suf, p2, s2), movP(ans, p3, s3); //refresh flg flg &= (bool)((p1 == s1) && (p2 == s2) && (p3 == s3)); val = (MSS){val.sum + sz * x, max(pre[p1].x * add_val + pre[p1].y, 0ll), max(suf[p2].x * add_val + suf[p2].y, 0ll), max(ans[p3].x * add_val + ans[p3].y, 0ll)}; } inline ll cac_direct(int l, int r){ //caculate directly int a_end = 0; for(int i = l; i <= r; ++i) asum[++a_end] = a[i] + add_val; for(int i = 1; i <= a_end; ++i) asum[i] += asum[i - 1]; ll _min = 0, res = 0; for(int i = 1; i <= a_end; ++i) res = max(res, asum[i] - _min), _min = min(_min, asum[i]); return res; } MSS cac(int l, int r){ MSS res = (MSS){0, 0, 0, 0}; int a_end = 0; for (int i = l; i <= r; ++i) asum[++a_end] = a[i] + add_val; for(int i = 1; i <= a_end; ++i) res.sum += asum[i], res.l = max(res.l, res.sum); res.sum = 0; for(int i = a_end; i >= 1; --i) res.sum += asum[i], res.r = max(res.r, res.sum); for(int i = 1; i <= a_end; ++i) asum[i] += asum[i - 1]; ll _min = 0; for(int i = 1; i <= a_end; ++i) res.ans = max(res.ans, asum[i] - _min), _min = min(_min, asum[i]); return res; } #undef direct_ts } blk[BLK_NUM]; int belong_blk[MAXN], pos_in_blk[MAXN]; int main(){ int n = readInt(), m = readInt(); for (register int i = 0, j = 1; i < n; i += BLK_SIZE, ++j){ for (register int k = 1; (k <= BLK_SIZE) && (i + k <= n); ++k){ blk[j].a[k] = readLL(), belong_blk[i + k] = j, pos_in_blk[i + k] = k; } blk[j].sz = min(BLK_SIZE, n - i), blk[j].build(); } int op, l, r; ll x; MSS res; for (register int i = 0; i < m; ++i){ op = readInt(), l = readInt(), r = readInt(); if (op == 1){ x = readLL(); if (belong_blk[l] == belong_blk[r]){ for (int j = pos_in_blk[l]; j <= pos_in_blk[r]; ++j) blk[belong_blk[l]].a[j] += x; blk[belong_blk[l]].build(); } else{ for (int j = pos_in_blk[l]; j <= blk[belong_blk[l]].sz; ++j) blk[belong_blk[l]].a[j] += x; blk[belong_blk[l]].build(); for (int j = belong_blk[l] + 1; j < belong_blk[r]; ++j) blk[j].add(x); for (int j = 1; j <= pos_in_blk[r]; ++j) blk[belong_blk[r]].a[j] += x; blk[belong_blk[r]].build(); } } else{ if (belong_blk[l] == belong_blk[r]) printf("%lld\n", blk[belong_blk[l]].cac_direct(pos_in_blk[l], pos_in_blk[r])); else{ res = blk[belong_blk[l]].cac(pos_in_blk[l], blk[belong_blk[l]].sz); for (register int j = belong_blk[l] + 1; j < belong_blk[r]; ++j) res = res + blk[j].val; res = res + blk[belong_blk[r]].cac(1, pos_in_blk[r]); printf("%lld\n", res.ans); } } } return 0; }
//refer to shadowice1984's solution
//Compiler optimization#pragma GCC optimize(3)#pragma GCC optimize("Ofast")
#include <cstdio>//type define#define ll long long//function define#define min(a,b) ((a<b)?a:b)#define max(a,b) ((a>b)?a:b)//NUM defineconst ll _MIN = (-(1ll << 47));#define MAXN 100010#define BLK_SIZE 110#define BLK_NUM 1005
inline int readInt(){ int x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
inline ll readLL(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
struct Point{ ll x, y; };
Point operator + (const Point &a, const Point &b){ return (Point){a.x + b.x, a.y + b.y};}
inline bool CompVal(const Point &a, const Point &b, const ll &c){ return ((b.x - a.x) * c >= b.y - a.y);}
inline bool Comp3(const Point &a, const Point &b, const Point &c){ return ((a.x - b.x) * (a.y - c.y) >= (a.y - b.y) * (a.x - c.x));}
inline bool Comp4(const Point &a, const Point &b, const Point &c, const Point &d){ return ((a.x - b.x) * (c.y - d.y) >= (a.y - b.y) * (c.x - d.x));}
struct MSS{ ll sum, l, r, ans;};
MSS operator + (const MSS &a, const MSS &b){ return (MSS){a.sum + b.sum, max(a.sum + b.l, a.l), max(a.r + b.sum, b.r), max(a.r + b.l, max(a.ans, b.ans))};}
Point stk[BLK_SIZE + 1];ll asum[BLK_SIZE + 1];
void getCH(Point *stk, int &top){ //get convex hull int i, r; for(i = 2, r = top, top = 1; i <= r; ++i){ while(top > 1 && Comp3(stk[top - 1], stk[top], stk[i])) --top; stk[++top] = stk[i]; }}
inline void insert(const Point &a){ stk[a.x].y = max(stk[a.x].y, a.y);}
struct Block{ //threshold of caculate directly #define direct_ts 16 //Member in long long ll a[BLK_SIZE + 1], add_val; ll thre_val; //Member in int int sz; //pre-[pre-suf-ans] int p1, p2, p3; //suf-[pr-suf-ans] int s1, s2, s3; //Member in MSS MSS val; //Membet in Point Point ans[BLK_SIZE + 1]; // prefix suffix Point pre[BLK_SIZE + 1], suf[BLK_SIZE + 1]; //Member in bool bool flg; //Functions //caculate directly inline int sol_direct(int l, int r){ ll tot = 0; for(int i = l + 1; i <= r; ++i) tot += a[i], ans[i] = (Point){i - l, tot}; for(int i = l + 2; i <= r; ++i){ tot = 0; Point* _new = ans + l + 1; for(int j = i; j <= r; ++j, ++_new) tot += a[j], _new->y = max(_new->y, tot); } s3 = r - l; getCH(ans + l, s3); return s3; } //caculate int sol(int l, int r){ if(r - l < thre_val) return 0; if(r - l <= direct_ts) return sol_direct(l, r); int mid = (l + r) >> 1; int resl = sol(l, mid), resr = sol(mid, r); for(int i = 1; i <= r - l; ++i) stk[i] = (Point){i, _MIN}; for(int i = l + 1; i <= l + resl; ++i) insert(ans[i]); for(int i = mid + 1; i <= mid + resr; ++i) insert(ans[i]); ll tot = 0; s1 = 0; for(int i = mid + 1; i <= r; ++i) ++s1, tot += a[i], pre[s1] = (Point){s1, tot}; getCH(pre, s1); tot = 0, s2 = 0; for(int i = mid; i > l; --i) ++s2, tot += a[i], suf[s2] = (Point){s2, tot}; getCH(suf, s2); //merge Convex Hull //go both direction int i = 1, j = 1; insert(pre[i] + suf[j]); for(; i != s1 && j != s2;){ if (Comp4(pre[i], pre[i + 1], suf[j], suf[j + 1])) ++j; else ++i; insert(pre[i] + suf[j]); } //go along one direction if(i != s1) for(++i; i <= s1; ++i) insert(pre[i] + suf[j]); if(j != s2) for(++j; j <= s2; ++j) insert(pre[i] + suf[j]); s3 = r - l; getCH(stk, s3); for(int i = 1; i <= s3; ++i) ans[l + i] = stk[i]; return s3; } inline void movP(Point *a, int &pos, int &t){ while(pos != t) if(CompVal(a[pos], a[pos + 1], -add_val)) break; else ++pos; } void build(){ //Make convex hull for (int i = 1; i <= sz; ++i) a[i] += add_val; add_val = 0; if (!flg){ //refresh flg flg = 1; for (int i = 1; i <= sz; ++i) flg = flg && (a[i] >= 0ll); } if (flg){ val.sum = 0; for (int i = 1; i <= sz; ++i) val.sum += a[i]; val.l = val.r = val.ans = val.sum; return ; } thre_val = ans[p3].x, sol(0ll, sz); ll tot = 0ll; s1 = 0ll; for (int i = 1; i <= sz; ++i) ++s1, tot += a[i], pre[s1] = (Point){s1, tot}; getCH(pre, s1); tot = 0ll, s2 = 0ll; for (int i = sz; i >= 1; --i) ++s2, tot += a[i], suf[s2] = (Point){s2, tot}; getCH(suf, s2); p1 = 1, movP(pre, p1, s1); p2 = 1, movP(suf, p2, s2); p3 = 1, movP(ans, p3, s3); //refresh flg again flg &= (bool)((p1 == s1) && (p2 == s2) && (p3 == s3)); //refresh val val = (MSS){tot, max(pre[p1].y, 0ll), max(suf[p2].y, 0ll), max(ans[p3].y, 0ll)}; } void add(ll x){ if (flg){ add_val += x; val.sum += sz * x; val.l = val.r = val.ans = val.sum; return ; } add_val += x; movP(pre, p1, s1), movP(suf, p2, s2), movP(ans, p3, s3); //refresh flg flg &= (bool)((p1 == s1) && (p2 == s2) && (p3 == s3)); val = (MSS){val.sum + sz * x, max(pre[p1].x * add_val + pre[p1].y, 0ll), max(suf[p2].x * add_val + suf[p2].y, 0ll), max(ans[p3].x * add_val + ans[p3].y, 0ll)}; } inline ll cac_direct(int l, int r){ //caculate directly int a_end = 0; for(int i = l; i <= r; ++i) asum[++a_end] = a[i] + add_val; for(int i = 1; i <= a_end; ++i) asum[i] += asum[i - 1]; ll _min = 0, res = 0; for(int i = 1; i <= a_end; ++i) res = max(res, asum[i] - _min), _min = min(_min, asum[i]); return res; } MSS cac(int l, int r){ MSS res = (MSS){0, 0, 0, 0}; int a_end = 0; for (int i = l; i <= r; ++i) asum[++a_end] = a[i] + add_val; for(int i = 1; i <= a_end; ++i) res.sum += asum[i], res.l = max(res.l, res.sum); res.sum = 0; for(int i = a_end; i >= 1; --i) res.sum += asum[i], res.r = max(res.r, res.sum); for(int i = 1; i <= a_end; ++i) asum[i] += asum[i - 1]; ll _min = 0; for(int i = 1; i <= a_end; ++i) res.ans = max(res.ans, asum[i] - _min), _min = min(_min, asum[i]); return res; } #undef direct_ts} blk[BLK_NUM];
int belong_blk[MAXN], pos_in_blk[MAXN];
int main(){ int n = readInt(), m = readInt(); for (register int i = 0, j = 1; i < n; i += BLK_SIZE, ++j){ for (register int k = 1; (k <= BLK_SIZE) && (i + k <= n); ++k){ blk[j].a[k] = readLL(), belong_blk[i + k] = j, pos_in_blk[i + k] = k; } blk[j].sz = min(BLK_SIZE, n - i), blk[j].build(); } int op, l, r; ll x; MSS res; for (register int i = 0; i < m; ++i){ op = readInt(), l = readInt(), r = readInt(); if (op == 1){ x = readLL(); if (belong_blk[l] == belong_blk[r]){ for (int j = pos_in_blk[l]; j <= pos_in_blk[r]; ++j) blk[belong_blk[l]].a[j] += x; blk[belong_blk[l]].build(); } else{ for (int j = pos_in_blk[l]; j <= blk[belong_blk[l]].sz; ++j) blk[belong_blk[l]].a[j] += x; blk[belong_blk[l]].build(); for (int j = belong_blk[l] + 1; j < belong_blk[r]; ++j) blk[j].add(x); for (int j = 1; j <= pos_in_blk[r]; ++j) blk[belong_blk[r]].a[j] += x; blk[belong_blk[r]].build(); } } else{ if (belong_blk[l] == belong_blk[r]) printf("%lld\n", blk[belong_blk[l]].cac_direct(pos_in_blk[l], pos_in_blk[r])); else{ res = blk[belong_blk[l]].cac(pos_in_blk[l], blk[belong_blk[l]].sz); for (register int j = belong_blk[l] + 1; j < belong_blk[r]; ++j) res = res + blk[j].val; res = res + blk[belong_blk[r]].cac(1, pos_in_blk[r]); printf("%lld\n", res.ans); } } } return 0;}
标签:suf,ch,val,Point,int,s2,分块,毒瘤 来源: https://www.cnblogs.com/linzhengmin/p/10830454.html