The 16th Heilongjiang Provincial Collegiate Programming Contest
阿新 • • 發佈:2021-07-16
2021 黑龍江省賽
A: And RMQ
線段樹區間與 ->1、維護區間或,複雜度可大可小
2、吉司機線段樹
https://codeforces.com/gym/103107/problem/A const int maxn = 4e5 + 10; int a[maxn]; int n, m; struct seg{ int t[maxn << 2], orr[maxn << 2]; #define root 1, 1, n #define lr rt << 1 #define rr rt << 1 | 1 #define mid (l + r >> 1) #define lson lr, l, mid #define rson rr, mid + 1, r inline void pushup(int rt) { t[rt] = max(t[lr], t[rr]); orr[rt] = orr[lr] | orr[rr]; } void build(int rt, int l, int r) { if(l == r) { t[rt] = orr[rt] = a[l]; return ; } build(lson); build(rson); pushup(rt); } //維護區間或,顯然這個值或區間所有數都是區間的數,那麼如果v&區間或不變,代表v比區間或更大,不需要更新 void ord(int rt, int l, int r, int L, int R, int v) { if(l == r) { t[rt] = orr[rt] &= v; return ; } if(L <= mid && (orr[lr] & v) < orr[lr]) ord(lson, L, R, v); if(R > mid && (orr[rr] & v) < orr[rr]) ord(rson, L, R, v); pushup(rt); } void update(int rt, int l, int r, int pos, int v) { if(l == r) { t[rt] = orr[rt] = v; return ; } if(pos <= mid) update(lson, pos, v); else update(rson, pos, v); pushup(rt); } int query(int rt, int l, int r, int L, int R) { if(l >= L && r <= R) return t[rt]; int res = 0; if(L <= mid) res = query(lson, L, R); if(R > mid) res = max(res, query(rson, L, R)); return res; } }T; signed main() { n = rd(), m = rd(); for(int i = 1; i <= n; ++ i) a[i] = rd(); T.build(root); for(int i = 1; i <= m; ++ i) { char op[4]; scanf("%s", op); int l = rd(), r = rd(), v; if(op[0] == 'A') { v = rd(); T.ord(root, l, r, v); } else if(op[0] == 'U') T.update(root, l, r); else printf("%d\n", T.query(root, l, r)); } return 0; }
D:Doin' Time
最簡單區間dp裸題
E: Elastic Search
AC自動機裸題
F:Function
尤拉篩的運用
G:Go? No
tarjan求割點連的最多橋數
H:Hack DSU!
簡單思維
L:Labi-Ribi
典中典貪心,生命值還能是負數,真是典中典
就是打怪獸模型,怪獸生命值\(h_i\),打一隻怪攻擊力增加\(c_i\),大於等於\(h_i\)才能攻擊,問一開始最少攻擊力
顯然對於\(c_i >= 0\),直接按h小的貪,對於\(c_i < 0\),按\(h_i+c_i\)大的貪即可,最後排序後就是求\(max_{i = 1}^n(h - pre_{~i - 1})\)
q = 1000,可以nq做法,q = 1e5,要離線線段樹求區間最大值
struct node{ int h, c; bool operator < (const node &x) const { if(c >= 0) return h < x.h; else return h + c > x.h + x.c; } }a[maxn], b[maxn]; int h[maxn]; void run() { int n = rd(), acnt = 0, bcnt = 0; for(int i = 1; i <= n; ++ i) h[i] = rd(); for(int i = 1; i <= n; ++ i) { int ta = rd(), tb = rd(), tc = tb - ta; if(tc >= 0) b[bcnt ++] = {h[i], tc}; else a[acnt ++] = {h[i], tc}; } sort(a, a + acnt); sort(b, b + bcnt); int ans = -0x3f3f3f3f3f3f3f3f, now = 0; for(int i = 0; i < bcnt; ++ i) { ans = max(ans, b[i].h - now); now += b[i].c; } for(int i = 0; i < acnt; ++ i) { ans = max(ans, a[i].h - now); now += a[i].c; } printf("%lld\n", ans); int q = rd(); for(int i = 1; i <= q; ++ i) { int th = rd(), ta = rd(), tb = rd(); if(tb - ta >= 0) { node tmp = {th, tb - ta}; int pos = lower_bound(b, b + bcnt, tmp) - b; for(int j = bcnt; j > pos; -- j) b[j] = b[j - 1]; b[pos] = tmp; bcnt ++; } else { node tmp = {th, tb - ta}; int pos = lower_bound(a, a + acnt, tmp) - a; for(int j = acnt; j > pos; -- j) a[j] = a[j - 1]; a[pos] = tmp; acnt ++; } ans = -0x3f3f3f3f3f3f3f3f, now = 0; for(int j = 0; j < bcnt; ++ j) { ans = max(ans, b[j].h - now); now += b[j].c; } for(int j = 0; j < acnt; ++ j) { ans = max(ans, a[j].h - now); now += a[j].c; } printf("%lld\n", ans); } return ; }