1. 程式人生 > 其它 >The 16th Heilongjiang Provincial Collegiate Programming Contest

The 16th Heilongjiang Provincial Collegiate Programming Contest

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 ;
}